Powershell ps2exe config variable - powershell

I would like To store a variable in a config file for a .ps1(powershell script) converted to .exe using ps2exe
$LnkPath="...\" #Directory Path of .lnk
$LnkFile="\nnnn.lnk" #name of .lnk file
Invoke-Item $ScriptPath + $LnkFile
I was hoping to have $LnkFile and $LnkPath as config file variables so if the version of the lnk stops working, i can just point to a new lnk.
There is a reason why the version of the .lnk file stops working, but it is complicated, and not worth anyone's time.
edit:

The config file created with the optional -configFile switch isn't meant for use by the wrapped script - it merely contains runtime metadata for the generated executable (in the form of an XML file placed alongside the executable with additional extension .config).
However, you can create your own config file.
While PowerShell has a configuration-data format that uses hashtable-literal syntax, which can be read with Import-PowerShellDataFile, as of PowerShell 7.2.x there is no way to create this format programmatically.
A simple alternative that supports both reading and programmatic creation is to use a JSON file:
The following assumes that your script file is foo.ps1, to be converted to foo.exe, with a configuration file foo.json located in the same directory (which you'll have to bundle with your .exe file when deploying it):
First, create your JSON config file:
#{ LnkPath = '...\'; LnkFile = 'nnnn.lnk' } | ConvertTo-Json > foo.json
Now you can read this file from foo.ps1 / foo.exe as follows:
# Determine this script's / executable's full path.
$scriptOrExePath =
if ($PSCommandPath) { # Running as .ps1
$PSCommandPath
} else { # Running as .exe"
Convert-Path ([Environment]::GetCommandLineArgs()[0])
}
# Look for the JSON config file in the same directory as this script / executable, load it and parse it into an object.
$config =
Get-Content -Raw ([IO.Path]::ChangeExtension($scriptOrExePath, '.json')) |
ConvertFrom-Json
# $config is now an object with .LnkPath and .LnkFile properties.
$config # Output for diagnostic purposes.
Note the need to use [Environment]::GetCommandLineArgs() to determine the executable path when running as an .exe file, because the usual automatic variables indicating the script path ($PSCommandPath) and script directory ($PSScriptRoot) aren't available then.

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%"

Powershell module function not visible in Get-Modules

I have a simple powershell module containing a single function, an abridged version of this is as follows:
function My-Func
{
.
.
.
}
Export-ModuleMember -Function 'My-Func'
My manifest file contain a line to explicitly export this:
FunctionsToExport = "My-Func"
Everything uploads to the powershell gallery via Publish-Module without any problems, then when I come to install this and run Get-Module, I do not see the function in the export commands column of the output, also I when I attempt to call the function powershell tells me it does not exist.
I have a psm1 file for my module and a psd1 manifest, for some reason when I only see Manifest as the module type, I'm guessing I need to see script ?.
Any ideas ?
in your .psm1:
remove the Exported-ModuleMember line
in your .psd1:
RootModule = 'yourmodule.psm1'
FunctionsToExport = #('function1','function2')
the psd1 file FunctionsToExport works like the Exported-ModuleMember command. it's a cleaner way to define things from one centralized file.

Creating CSV file as an object

I have got a robust script which gets, parse and uses some data from .csv file. To run the script I can use
.\script.ps1 -d data_file.csv
The thing is I cannot interfere into script itself that is why i need to create some kind of a wrapper which will create new csv file and use script.ps1 with a new made file. I am wondering if there is a possibility to create a csv file as an object which will be passed directly to the command like this
.\script.ps1 -d csv_file_as_object.csv
without creating file in some path directory.
What you'd need in this case is the equivalent of Bash's process substitution (<(...)), which, in a nutshell, would allow you to present a command's output as the content of a temporary file whose path is output:
.\scripts.ps1 -d <(... | ConvertTo-Csv) # !! does NOT work in PowerShell
Note: ... | ConverTo-Csv stands for whatever command is needed to transform the original CSV in-memory.
No such feature exists in PowerShell as of Windows PowerShell v5.1 / PowerShell Core v6.1, but it has been proposed.
If .\scripts.ps1 happens to also accept stdin input (via pseudo-path - indicating stdin input), you could try:
... | ConvertTo-Csv | .\script.ps1 -d -
Otherwise, your only option is to:
save your modified CSV data to a temporary file
pass that temporary file's path to .\script.ps1
remove the temporary file.

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.

Invoke FCIV within Powershell Script

I am using the FCIV ( Microsoft File Checksum Integrity Verifier ) executable to automatically calculate checksums for certain files.
I want to invoke this executable within a powershell script. This is my snippet within Powershell.
& "Path to FCIV.exe" –add "Base Dir" -bp "Base Dir" -r –xml "Path to XML"
This commands basically recurses and calculates checksums for all files under "Base Dir" and then outputs into an XML file. I am able to execute this command on Powershell prompt. But when I add this line into a script and execute the script, I get this error.
–add\*
Error msg : The system cannot find the path specified.
Error code : 3
I have tried everything from adding FCIV to PATH environment variable as well as providing the whole path to files.
Any suggestions on how to overcome this?