Batch script: Pass returned GUID as URL parameter for desktop shortcut

Viewed 94

I'm trying to create desktop shortcuts to a private page we work with that will open in Edge, direct to a specific URL, and pass the GUID as a URL parameter.

I've tried the following but as you can expect, only the string "powershell" is passed on to the URL, not the returned GUID.

SET a=powershell -Command "[guid]::NewGuid().ToString()"
C:\Windows\System32\cmd.exe /c start msedge "https://www.website.com/page?user="%a% --no-first-run

How can I replace the %a% portion of the URL with the returned contents of the system GUID?

powershell -Command "[guid]::NewGuid().ToString()"
2 Answers

Note:

  • This answer addresses the question as asked: it captures the output from a PowerShell command in a batch-file variable for later use in the same batch file.

  • Alternatively, the specific task at hand can also be performed in full by a single PowerShell command, as shown in zett42's helpful answer.


Batch files (executed by cmd.exe) have no concept of a what is known as command substitution in POSIX-compatible shells (a feature that PowerShell itself provides too, though it has no official name there): the ability to assign a command's output to a variable.[1]

Instead, you must use a for /f loop to capture command output in a variable (which generally loops over each output line, but in your case there is only one output line):

@echo off
setlocal

:: Capture the output from a PowerShell command in variable %guid%, via 
:: a for /f loop:
for /f "usebackq delims=" %%a in (`powershell -Command "[guid]::NewGuid().ToString()"`) do set "guid=%%a"

:: Note: No need for `cmd /c` from a batch file to use `start`
start "" msedge "https://www.website.com/page?user=%guid%" --no-first-run

Note: setlocal, while not strictly necessary, localizes any variable definitions to the batch file at hand.

  • Run for /? in a cmd.exe session for help.

  • This answer discusses using for /f to capture command output in more detail; notably:

    • usebackq isn't strictly necessary here, but is generally advisable to give you the freedom to use both ' and " quoting in the command line being invoked.

    • Similarly, delims= isn't strictly necessary here, since the output by definition contains no spaces, but it is generally advisable if the intent is to capture an output line in full.

  • The "" as the first start argument isn't strictly necessary here, but in general it is useful when invoking applications whose paths must be double-quoted. Without "" as the first argument, a double-quoted application path would be interpreted as starts window-title argument (which only meaningfully applies to console applications).


[1] In POSIX-compatible shells, use $(...) (e.g, captured="$(whoami)"). In PowerShell, you can use the command -as-is as the RHS of the assignment (e.g., $captured = whoami)

It is possible to do all of this directly using a PowerShell one-liner:

powershell -noprofile -command start msedge \"https://www.website.com/page?user=$(New-Guid) --no-first-run\"
  • Passing -noprofile to powershell.exe is most of the time a good idea to reduce startup time and provide a more predictable environment as no user profile will be loaded.
  • start is an alias for the Start-Process command.
  • Here start gets passed two positional arguments, the name of the process to start (-FilePath parameter) and the process's arguments as a single string (-ArgumentList parameter). Therefore, the 2nd argument must be quoted. To pass the quotes from the command processor cmd.exe through to PowerShell, they must be backslash-escaped.
  • Within the process's parameter string, the subexpression operator $(…) is used to call the New-Guid command inline and convert it to a string (by implicitly calling the .ToString() method of the Guid object it returns).
  • If you actually need to use the GUID as a variable in other parts of your batch script (which is not clear from the question), then this helpful answer provides a solution.
Related