PowerShell App.Config - powershell

Has anyone worked out how to get PowerShell to use app.config files? I have a couple of .NET DLL's I'd like to use in one of my scripts but they expect their own config sections to be present in app.config/web.config.

Cross-referencing with this thread, which helped me with the same question:
Subsonic Access To App.Config Connection Strings From Referenced DLL in Powershell Script
I added the following to my script, before invoking the DLL that needs config settings, where $configpath is the location of the file I want to load:
[appdomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $configpath)
Add-Type -AssemblyName System.Configuration
See this post to ensure the configuration file specified is applied to the running context.

I'm guessing that the settings would have to be in powershell.exe.config in the powershell directory, but that seems to be a bad way of doing things.
You can use ConfigurationManager.OpenMappedExeConfiguration to open a configuration file based on the executing DLL name, rather than the application exe, but this would obviously require changes to the DLLs.

Attempting a new answer to an old question.
I think the modern answer would be: don't do that. PowerShell is a shell. The normal way of passing information between parts of the shell are shell variables. For powershell that would look like:
$global:MyComponent_MySetting = '12'
# i.e.
$PSDefaultParameterValues
$ErrorActionPreference
If settings is expected to be inherited across processes boundaries the convention is to use environment variables. I extend this to settings that cross C# / PowerShell boundary. A couple of examples:
$env:PATH
$env:PSModulePath
If you think this is an anti-pattern for .NET you might want to reconsider. This is the norm for PAAS hosted apps, and is going to be the new default for ASP.NET running on server-optimized CLR (ASP.NET v5).
See https://github.com/JabbR/JabbRv2/blob/dev/src/JabbR/Startup.cs#L21
Note: at time of writing I'm linking to .AddEnvironmentVariables()
I've revisited this question a few times, including asking it myself. I wanted to put a stake in the ground to say PowerShell stuff doesn't work well with <appSettings>. IMO it is much better to embrace the shell aspect of PS over the .NET aspect in this regards.
If you need complex configuration take a JSON string. POSH v3+ has ConvertFrom-JSON built-in. If everything in your process uses the same complex configuration put it in a .json file and point to that file from an environment variable.
If a single file doesn't suffice there are well established solutions like the PATH pattern, GIT .gitignore resolution, or ASP.NET web.config resolution (which I won't repeat here).

Related

Loading/use CsvHelper in PowerShell 7/.NET 5

Long story short - requesting assistance loading/using CsvHelper in PS 7 w/.NET 5. Dll loads fine but no exported commands available. Added a manifest (nested, root, etc) with full export didn't expose. Assistance would be greatly appreciated.
Long story long - Have a system with fairly vanilla installs of pwsh v7.1.3 and .NET v5.0.300. I've been assigned a project to work with very large CSV files and process them with SQLBULKCOPY. The files will have formatting challenges as well as date (datetime2) fun so a Csv parser seems to be the best course of action.
After seeing that CsvHelper can cut through the parsing requirements, is compiled for .NET 5 (no dependencies), and reading reviews showing 20%+ better performance than another DLL (lu...) being tested I would like to leverage it for the project.
This solution will be used on systems with no access to the internet and users with limited skills, so the hope is to use just include the CsvHelper dll in the script module directory.
Loading the CsvHelper.dll (net5.0) file import-module "...\CsvHelper.dll" appears to work. Get-Module shows the dll is loaded but doesn't show any exported commands. Get-Command doesn't either. I've tried creating a manifest file for the DLL (nestedmodules, rootmodule, etc. and export specific publics, *) but am unsuccessful. I'm sure I'm missing something simple and would appreciate assistance. Thanks much.
When I started this project the first test was using a Lumenworks parser. It can be loaded into PS and used directly. That was nice and it set my head in that specific direction. Moving into CsvHelper I was wanting (hoping) to stay in PS only. There were bureaucratic motivations to not to go into studio, compile a dll, and the like.
My hope was to load the helper dll in PS and then inline the C# code. Something along the lines of:
Import-Module "C:\...\CsvHelper.dll"
or
$Assem = (
<?? for csvhelper>
)
with
$source = #"
using CsvHelper;
<C# around using CsvHelper>
"#
and appropriate Add-Type
Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp
What I wanted to do can probably be done but I don't have the skills for it. For now I'm going with a Studio project. Will build set it to do what I want, use it in PS for the solution and deal with the politics.
Appreciate the inputs.

Access dll api by batch/powershell script [duplicate]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a DLL file and I want to execute it on Windows. I obtained this DLL file from a challenge site which alleges the DLL should be executed independently.
To run the functions in a DLL, first find out what those functions are using any PE (Portable Executable) analysis program (e.g. Dependency Walker).
Then use RUNDLL32.EXE with this syntax:
RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments>
dllname is the path and name of your dll file, entrypoint is the function name, and optional arguments are the function arguments
You can execute a function defined in a DLL file by using the rundll command. You can explore the functions available by using Dependency Walker.
While many people have pointed out that you can't execute dlls directly and should use rundll32.exe to execute exported functions instead, here is a screenshot of an actual dll file running just like an executable:
While you cannot run dll files directly, I suspect it is possible to run them from another process using a WinAPI function CreateProcess:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
DLLs are shared libraries which are used by other windows programs while EXEs are the files which are actually executed and are linked to DLL files so that they can use DLLs. Both are of same format, PE(portable executable or format of machine code in windows in simple words).
In other words EXEs contain the entry point(main) and the DLLs contain the library functions.. You cannot execute a file which just contains library functions you can just use them via other programs.
But still there are programs like rundll32.exe which provides that entry point and some minimal framework required by DLL functions to be called.
The point that I want to make is, you can never execute a DLL file you can just use it's code by providing an entry point through an EXE or some other program.
You can't "execute" a DLL. You can execute functions within the DLL, as explained in the other answers. Although .EXE files and .DLL files are essentially identical in terms of format, the distinguishing feature of an .EXE is that it contains a designated "entry point" to go and do the thing the EXE was created to do. DLLs actually have something similar, but the purpose of the "dll main" is just to perform initialization and not fulfill the primary purpose of the DLL; that is for the (presumably) various other functions it contains.
You can execute any of the functions exported by a DLL, assuming you know which one you want to execute; an EXE may contain a whole lot of functions, but one and only one is specially designated to be executed simply by "running" it.
To Run a .dll file..First find out what are functions it is exporting..Dll files will excecute
the functions specified in the Export Category..To know what function it is Exporting refer "filealyzer"
Application..It will show you the export function under "PE EXPORT" Category..Notedown the
function name--
Then open the command prompt,Type Rundll32 dllname,functionname
(dllname--name of your dll)
(Functionname-- name of the function you found under the PE Export)
Note:Makesure that your command prompt location is your dll file location
It should be mentioned that since it is entirely possible to run DLL's just as any other executable, it has long been considered a security issue. As such, there have been a number of security improvements and registry hacks (sorry no longer have ref-links) that prevents running DLL's from regular user space without extra privileges.
As a good example. I recall making these hacks, but since I no longer remember what exactly I did. I can no longer run any DLLs from normal user shell environment, even though starting various Win apps from GUI works just fine.
That said, one should definitely read "Dynamic-Link Library Security" and "Best Practices to Prevent DLL Hijacking".
.DLL files are not executable in the sense that .EXE/.COM/.BAT files are executable, so I'm not sure what you mean.
You can use the Dependency Walker application that comes with the Windows SDK to interrogate a .DLL and see what functions are exported by the file.
The following series of steps might be helpful:
Open Windows Explorer
In the top-left corner, click "Organize"
select "Folder and Search Options"
Switch to the "View" tab
Scroll down and uncheck "Hide file extensions for known file types"
Click OK
Now find the dll file
Right-click on it and select "Rename"
Change the extension(what comes after the last .) and change it to .exe

How do I generate a self-signed certificate and use it to sign my powershell script?

So I've been researching/googling for the last 2 hours, and I'm practically at the point of tears...
I can't use New-SelfSignedCertificate because I'm on Windows 7.
I can't use makecert because of a bug that won't allow me to install the SDK for Windows 7 because it thinks I have a pre-release version of .NET 4, but I don't. Trying to install .NET 4 informed me I have a new or better version.
I tried a registry hack that I found to get around this, which unfortunately didn't work.
I've downloaded this
https://gallery.technet.microsoft.com/scriptcenter/Self-signed-certificate-5920a7c6#content
But can't seem to manage to get through all the steps I need to actually get my script signed so I can give it to other people to use safely.
I think I've managed to create the certificate (although I'm not sure if I did it right).
From what I can tell I need to apply a password or key to it now, and then export it? I'm still not sure how I specifically sign my script, so others can execute it as 'Signed'.
Thanks guys.
Alternatively all this could possibly be unnecessary if anyone knows how I can get relative .ps1 paths working in a .exe file?
The script works fine as a .ps1, but as soon as I compile it into a .exe using PowerGUI, these lines don't work.
. .\Import-XLS.ps1
$OutFile = ".\TEST$(get-date -Format dd-MM).txt"
$Content = Import-XLS '.\TEST.xlsx'
I instead get things like
"The term '.\Import-XLS.ps1' is not recognised as the name of a cmdlet, along with some reference to a Appdata\Local\Temp\QuestSoftware\PowerGUI\ folder.
So I'm guessing PowerGUI is doing something weird, but I don't know how else to convert a .ps1 into a .exe.
Depending on the answer to the main question, I may submit a new question for the .exe one officially.
Thanks guys.
So I ended up resolving this issue with a combination of two things.
Split-Path $MyInvocation.MyCommand.Path
and
[System.AppDomain]::CurrentDomain.BaseDirectory}
I needed to use both, as the former worked in a .ps1 but not in a compiled .exe, while the latter worked in a compiled .exe, but not in a .ps1.
As the PowerGUI compiled .exe has a consistent path folder name, I ended up using the following.
$ScriptPath = Split-Path $MyInvocation.MyCommand.Path
if ($ScriptPath -match 'Quest Software') {$ScriptPath = [System.AppDomain]::CurrentDomain.BaseDirectory}
I also included the Function into the .exe (but it wasn't necessary).
I then used $OutFile = "$ScriptPath\<Filename>.txt"
and $Content = Import-XLS "$ScriptPath\<Filename>.xlsx"
This means I can now use a .exe instead of trying to get a working certificate for the script. While also being able to quickly test changes to it while it's still a .ps1.
I hope this is helpful for others using PowerGUI to make .exe's in the future, who also need to use relative paths.
Thanks to those that provided help and advice.
So I have not used PowerGUI to create .exe files from scripts so this is a bit of a shot in the dark but I am guessing it just does not implement dot-sourcing external files, if that is the only thing preventing you from deploying the code why not just copy the functions from Import-XLS.ps1 into the body of your script?

TFS 2010: run powershell script stored in source control

We've started using TFS2010 over at the company I work at. We create e-commerce web applications (shopping sites). I'm creating a custom template to deploy web projects after a build using a build template.
I've looked at the web deploy tool, but MSDN seems to indicate that it can only do initial deployments, and I need to be able to do incremental deployments with the same script.
I'm thinking of using the invokeActivity activity in the template to use powershell to do the job by specifying an FTP script which automatically copies the output of a build to a designated FTP site and then runs the SQL (upgrade) scripts, if needed by using SSH or s powershell remoting interactive session. (possibly specified in a separate SQL script)
There is some unknown for me which I can't get clear through the use of google:
When queuing a build, will I be able to let the user specify a script present in source control ( e.g. $(source)\scripts\ftpscript.ps1 ) as the script which is to be used? Will powershell be able to access/use that file? or should I copy it to the build directory and specify when I run it? (I don't know how to set up the template to get files from source control, so a pointer to some helpful info how to do that would be very much appreciated)
If the previous just doesn't work at all, could I create a folder \scripts\ in my website project, commit that to source control and then use BuildDetail.DropLocationRoot & "\scripts\" as the location for the script and fore a copy of the script files by enabling the force copy option?
To run a PowerShell script I think you can use the InvokeProcess activity which would trigger something like this:
%windir%\system32\windowspowershell\v1.0\powershell.exe "$(SolutionRoot)\test.ps1
And yes, you can reach a script file present in source control using the "SourcesDirectory" keyword.

Environment.CurrentDirectory with NUnit GUI differs to the TeamCity value, how can I sync them?

As above really, I have some integration tests that use files from a relative file path. To help picture it here is the file structure:
/Dependencies
/VideoTests/bin/release/video.dll
/SearchTests/bin/release/search.dll
/OtherProjects
The GUI is running the tests from the root, however when TeamCity runs the tests it is running the tests from each test dlls bin directory. Now I don't mind which one I can get to follow the other but I do need them to be the same otherwise my relative paths just won't work!
Any ideas?
P.S. Using TeamCity 5.0 and NUnit 2.5.
You probably don't want to rely on CurrentDirectory. I'd suggest reading the doc, but the main point you'll want to take away is that the CurrentDirectory is where the .exe was started from: it could be any path in the system. For example, let's assume your users add your .exe (or whatever .exe uses your DLLs) to their path. They could then navigate to c:\foo\bar and start the .exe from there, which would set the CurrentDirectory to "C:\foo\bar" and you may not be able to deal with that.
I think it would be preferable for you to rework whatever you're doing so you don't rely on CurrentDirectory. What problems are you encountering by relying on CurrentDirectory right now?
Have you made sure that both TeamCity and NUnit are using the same working directory when starting the application?
And if they aren't, you could adjust the current directory in the test code.