Is it possible to create a path which consist of an environment variable + the filename - powershell

I want to copy an .exe file to /App/Data/Local/Temp and run the exe afterwards. Instead of adding the full, static filepath i would like to use $env:TEMP to have no dependency to the user account inside the ps. Based of $env:TEMP + the .exe file i tried to create a new variable $LocalInstall which i could use later inside the ps but it seems not to work.
$LocalInstallFile=$env:TEMP."\Agent.exe"
Later $LocalInstallFile should be used to run the installation with installation properties
Invoke-Expression "$LocalInstallFile /DIR=c:\"
Could i instead also use
Invoke-Expression "$env:TEMP\Agent.exe"

The expression
$LocalInstallFile=$env:TEMP."\Agent.exe"
will expand the $env:TEMP environment variable and then try to invoke the property called "\Agent.exe" on the string object which, of course, doesn't exist, so $LocalInstallFile is null. Instead, create the string like this:
$LocalInstallFile="$env:TEMP\Agent.exe"

Related

How to read a text file to a variable in batch and pass it as a parameter to a powershell script

I have a powershell script that generates a report, and I have connected it to an io.filesystemwatcher. I am trying to improve the error handling capability. I already have the report generation function (which only takes in a filepath) within a try-catch loop that basically kills word, excel and powerpoint and tries again if it fails. This seems to work well but I want to embed in that another try-catch loop that will restart the computer and generate the report after reboot if it fails a second consecutive time.
I decided to try and modify the registry after reading this article: https://cmatskas.com/configure-a-runonce-task-on-windows/
my plan would be, within the second try-catch loop I will create a textfile called RecoveredPath.txt with the file path being its only contents, and then add something like:
Set-ItemProperty "HKLMU:\Software\Microsoft\Windows\CurrentVersion\RunOnce" -Name '!RecoverReport' -Value "C:\...EmergencyRecovery.bat"
Before rebooting. Within the batch file I have:
set /p RecoveredDir=<RecoveredPath.txt
powershell.exe -File C:\...Report.ps1 %RecoveredDir%
When I try to run the batch script, it doesn't yield any errors but doesn't seem to do anything. I tried adding in an echo statement and it is storing the value of the text file as a variable but doesn't seem to be passing it to powershell correctly. I also tried adding -Path %RecoveredDir% but that yielded an error (the param in report.ps1 is named $Path).
What am I doing incorrectly?
One potential problem is that not enclosing %RecoveredDir% in "..." would break with paths containing spaces and other special chars.
However, the bigger problem is that using mere file name RecoveredPath.txt means that the file is looked for in whatever the current directory happens to be.
In a comment your state that both the batch file and input file RecoveredPath.txt are located in your desktop folder.
However, it is not the batch file's location that matters, it's the process' current directory - and that is most likely not your desktop when your batch file auto-runs on startup.
Given that the batch file and the input file are in the same folder and that you can refer to a batch file's full folder path with %~dp0 (which includes a trailing \), modify your batch file to look as follows:
set /p RecoveredDir=<"%~dp0RecoveredPath.txt"
powershell.exe -File C:\...Report.ps1 "%RecoveredDir%"

how to add variables together in VSTS

I want to use a variable which is composed of another vsts variable and text, for instance:
vnetname = $vnet_prefix + "vnetid"
However i get an error saying that "A positional parameter cannot be found that accepts argument +.
Anyone advise?
If you mean use the variable in build/release processes, then you can add a variable like this (reference below screenshot):
vnetname = $(vnet_prefix)_vnetid
Then you can use the variable $vnetname or $(vnetname) directly, see Build variables-Format for how to use the variables in different tools.
Alternatively you can pass the value with Logging Commands:
Copy and paste below strings then save as *.ps1 file:
$value = $env:vnet_prefix + "vnetid"
Write-Host "##vso[task.setvariable variable=vnetname]$value"
Check in the PS file
Add a PowerShell task to run the PS file
Use the variable $vnetname in later steps

Creating files at PSModulePath in batch

I am currently trying to write a batch program that installs a module named SetConsolePath.psm1 at the correct location. I am a beginner with Batch and I have absolutely no powershell experience.
Through the internet, I have learned how to display PSModulePath with powershell -command "echo $env:PSModulePath.
How can I, via .bat file, move SetConsolePath.psm1 from the desktop to the location displayed by powershell -command "echo $env:PSModulePath?
Thank you in advance, and I apologize for my lack of experience.
Before I answer, I must out that you do not want to copy PowerShell module files directly to the path pointed by PsModulePath. You really want to create a folder inside PSModulePath and copy the files there instead.
The prefix env in a Powershell variable indicates an environment variable. $env:PSModulePath is actually referring to the PSMODULEPATH environment variable. On the command line, and in batch files, environment variables can be displayed by placing the name between percent symbols. (In fact, you could have displayed this value by typing echo %PSMODULEPATH% instead.)
To reference the desktop folder, have a look at this answer, which shows you how to use another environment variable, USERPROFILE.
Therefore, to copy the file from the desktop directory to the path specified in PSModulePath, you would do this:
COPY "%USERPROFILE%\Desktop\SetConsolePath.psm1" "%PSMODULEPATH%"
And, as I warned earlier, you really should copy the file to a folder underneath PsModulePath. So what you really want is:
IF NOT EXIST "%PSMODULEPATH%\MyNewFolder" MKDIR "%PSMODULEPATH%\MyNewFolder"
COPY "%USERPROFILE%\Desktop\SetConsolePath.psm1" "%PSMODULEPATH%\MyNewFolder"

How do I turn a collection of script files into a module?

Do you guys know, whether it's possible to convert PowerShell project consisting solely of functions, into module? What I want to achieve is to create distributable module of all my functions so others can use it. But without spending time of converting all functions into cmdlets.
Each of my functions is in separate file. When I then create *.psd1 and I try to include functions via 'FunctionsToExport', it doesn't work. I can't see my functions after module is loaded.
Is it even possible to export function from module when they're NOT (all of them) inside a .psm1 file? I'm still trying to figure out real differences and use of *psd1 and *psm1 files.
Yes, you can turn a bunch of .ps1 files into a module. Create a new folder in your module directory $env:USERPROFILE\Documents\WindowsPowerShell\Modules and put all the .ps1 files in that folder. Also create two text files <foldername>.psm1 and <foldername>.psd1 in the folder, so that you have a structure like this:
$env:USERPROFILE
`-Documents
`-WindowsPowerShell
`-Modules
`-MyModule
+-MyModule.psd1
+-MyModule.psm1
+-script1.ps1
+-script2.ps1
:
`-scriptN.ps1
Put the following line in the .psm1 file, so that it "imports" all .ps1 files:
Get-ChildItem -Path "$PSScriptRoot\*.ps1" | % { . $_.FullName }
and specify your metadata in the module manifest (the .psd1 file), e.g.:
#{
ModuleToProcess = 'MyModule.psm1'
ModuleVersion = '1.0'
GUID = '6bc2ac1e-2e88-4bc3-ac84-ecd16739b6aa'
Author = 'Matthew Lowe'
CompanyName = '...'
Copyright = '...'
Description = 'Description of your module.'
PowerShellVersion = '2.0'
FunctionsToExport = '*'
CmdletsToExport = ''
VariablesToExport = ''
AliasesToExport = ''
}
A GUID can be generated for instance via [guid]::NewGuid().
Here's a very simple way of doing it, without including your functions through dot sourcing mode, as it's done in the other answer:
Create a folder C:\MyModules.
Inside this folder, create an empty file named MyModules.PSM1.
Append to MyModules.PSM1 file, all functions (they don't need to be advanced) you want in the module.
YOU ARE DONE.
Now, you have a folder ( C:\MyModules ) that you must install in the target machine.
To install it in the target machine (per user), copy the folder C:\MyModule to the user's default module location (i.e. folder): $home\Documents\WindowsPowerShell\Modules.
Now, this user can type in any PowerShell session the first letter(s) of any function included in your module, that PowerShell's IntelliSense will recognize the function from your module (and uggest the completion substring).
If you don't like the name MyModule, you can change it, as long as you change the folder name as well as the PSM1 file name.
You can also opt to install your module for all users: help about_modules.

Why doesn't shell %variable% work when set from PowerShell?

I am inserting a variable string in my PATH variable. I set the variables in following manner:
$var="MyTestPath"
$mypath=[environment]::GetEnvironmentVariable("PATH",[system.environmentvariabletarget]::User)
[environment]::SetEnvironmentVariable("TEST",$var,[system.environmentvariabletarget]::User)
[environment]::SetEnvironmentVariable("PATH",$mypath+";%TEST%",[system.environmentvariabletarget]::User)
The above code doesn't work for me. %TEST% variable doesn't expand itself when I check the path in the new shell. It shows new path ending with %TEST%. This has always worked when I set this from GUI or from Windows shell prompt. Why is this behavior different when variables are set from PowerShell? Is this feature removed in PowerShell?
I don't want to do the following, because it will keep adding my variable to path everytime I run the script.
[environment]::SetEnvironmentVariable("PATH",$mypath+";"+$var,[system.environmentvariabletarget]::User)
Try change this line:
[environment]::SetEnvironmentVariable("PATH",$mypath+";%TEST%",[system.environmentvariabletarget]::User)
with:
$test =[environment]::GetEnvironmentVariable("test","user") # this retrieve the rigth variable value
[environment]::SetEnvironmentVariable("PATH", $mypath +";$test",[system.environmentvariabletarget]::User)
%test% have no meaning in powershell, can't be expandend as in CMD.
$env:test retrive only from system environment variable and not from user
You're wanting to effectively set a registry value (that corresponds to a env var) that uses REG_EXPAND_SZ. See this post for details on how to do that.