Adding .inf drivers using PowerShell, possible? - powershell

Are we able to install drivers via their .inf files etc. using a PowerShell cmdlet? When Googling I found, Add-WindowsDriver but I think this one is for an offline Windows image. Does that mean an image that is not currently used on an OS? If not, please teach me how to write the parameters. Thank you!

This PowerShell script will do what you want:
Get-ChildItem "C:\Driver File Location" -Recurse -Filter "*inf" | ForEach-Object { PNPUtil.exe /add-driver $_.FullName /install }

You don't need Powershell or advanced CMD programming, because pnputil.exe has a /subdirs command line switch and can slurp multiple .inf files at once. On my system (Windows 10 x64 21H2), you can simply execute:
pnputil /add-driver *.inf /install /subdirs
That does what I would expect.
pnputil.exe's help tells everything we need. Just execute pnputil without further parameters, and it outputs an understandable help screen (that is too long to post it here).

It can be done using the Install-DeviceDriver cmdlet from the DeviceManagement module. See my answer here for an example.

Related

How do i use Get-clipboard output in a powershell script?

i'm trying to use text that is inside the clipboard inside a powershell script. So what the purpose for the script, i want to be able to copy a file directory and then run the script so it uses the copied directory as a automatic destination. So my idea was to do something like this:
Copy-Item C:\Users\gif.gif -Destination "Copied Directory"
I'm very new to powershell scripting, so an explenation of what is going on would be nice but not needed. I origionlly thought that this could work but nope XD, this should have been a simple project but yeah it wasn't meant to be easy.
Copy-Item C:\Users\J.J\Documents\TouchPortal/Make_30fps_gif.bat -Destination | Get-Clipboard
Would love to get some help with this, and thank you in advance!
To complement Steven's helpful answer:
In Windows PowerShell only, you can use Get-Clipboard's -Format parameter to request clipboard data other than text.
In PowerShell [Core, v6+], this is no longer supported, and text is indeed the only data type supported by Get-Clipboard.
In Windows PowerShell, if you've used File Explorer to copy a directory to the clipboard (using the regular Copy shortcut-menu command or the Ctrl+C keyboard shortcut), you can access it as System.IO.DirectoryInfo instance by passing -Format FileDropList to Get-Clipboard.
Note: -Format FileDropList returns a collection of file-system-info objects, so as to also support multiple files/directories having been copied to the clipboard; thanks to member-access enumeration, however, you can treat this collection like a single object - assuming truly only one file or directory was copied.
# Note: Windows PowerShell only.
# The .FullName property returns the full directory path.
Copy-Item C:\Users\gif.gif -Destination (Get-Clipboard -Format FileDropList).FullName
In PowerShell [Core, v6+] you'll indeed have to use the Shift+right-click method and select Copy as path from the shortcut menu, in order to ensure that a file/directory is copied as a (double-quoted, full) path string, as shown in Steven's answer.
In PowerShell core including versions 6 & 7 Get-Clipboard only works with text. If you use it after copying a folder it will return null.
In PowerShell 5.1 (Windows PowerShell) you can use the -Format parameter with Get-Clipboard
See mklement0's answer for a better description and example using -Format.
If you need to use the newer versions, you can use the shift + context menu choice > Copy as Path to get the folder's string path on to the clipboard, but that will quote the path. The quoted path will then be rejected by Copy-Item.
However, you could quickly replace the quotes like below.
Copy-Item 'C:\temp\BaseFile.txt' -Destination (Get-Clipboard).Replace('"',"")
Caution though, this seems hazardous and I wouldn't advise it. I use Get-Clipboard all the time to get data into a console session and can attest that it's too easy to make mistakes. The clipboard is so transient and it's use so ubiquitous that even if you make this work it's bound to burn you at some point.
Maybe you can elaborate on what you're trying to do and why. Then we can brainstorm the best approach.

Alternatives to invoke-expression

I have this function:
function traced()
{
write-host "$args"
invoke-expression -Command "$args"
}
and I use it in several places like traced cp "$($_.FullName)" (join-path $directory $newfile) so that I have a log of all of the places that get copied (or removed, or whatever)
But when the directory contains spaces and dashes, it results in invoke-expression throwing.
I guess I could just define traced-cp and traced-rm, but if I have a lot of functions I want to trace, what's the generic answer? I just want a function that prints, then evaluates, the exact command its given. From what I understand, the & operator isn't what I want here-- It won't work for shell builtins.
[...] so that I have a log of all of the places that get copied (or removed, or whatever)
I'd strongly recommend you use transcript logging for this!
You can start a transcript interactively with the Start-Transcript cmdlet, but if you want to keep a transcript of every single instance of PowerShell you launch by default, I'd suggest turning it on by default!
Open the local policy editor (gpedit.msc) on your Windows box and navigate to:
Computer Configuration
> Administrative Templates
> Windows Components
> Windows PowerShell
Select the policy setting named "Turn on PowerShell Transcription", set it to Enabled, and optionally configure your preferred output directory (defaults to your home folder).
This way, you'll always have a full transcript of your interactions in PowerShell :)
Consider using argument splatting to build your command instead of building a string-based command with Invoke-Expression. I also don't know where you heard that & doesn't work with shell built-ins but it works with both commands and cmdlets.
Here is the official Microsoft documentation on splatting in Powershell.
This approach also eliminates the difficulty in crafting a command string correctly, having to escape characters, and dealing with path spaces - using splatting with named or positional arguments takes care of most of this for you.
I would suggest using -verbose with copy-item or remove-item, and also -passthru with copy-item.

Powershell Get-ChildItem doesn't work properly on IIS directory

I was going to write up a simple alias 'iis' to invoke the IIS Manager, which is 'C:\Windows\System32\inetsrv\InetMgr.exe'
set-alias iis "OpenIIS.ps1"
and in the OpenIIS.ps1 I have
$item = "C:\Windows\system32\inetsrv\InetMgr.exe"
invoke-item -path $item
This doesn't work. The error I get is "The system cannot find the file specified"
In fact, just doing a Get-ChildItem on the inetsrv won't show the InetMgr.exe (no difference with -Force switch)
Get-ChildItem C:\Windows\system32\inetsrv\*.exe -force
Obviously I can see it in Explorer and I can launch it using cmd, but not with Powershell it seems. Also, Powershell is running as Administrator.
What is going on?
As a workaround I tried creating a link to the file and then invoking that link from Powershell. I now get a 'NotSpecified' Win32Exception.
I have originally used 64 bit Powershell, but get the same result on the x86 Powershell (both run as Administrator)
Are you at the elevated PowerShell prompt? Some system files may not show up unless you use -Force parameter with Get-ChildItem.
I think evidently the file InetMgr.exe is not there as when I do a get-childitem in the mentioned directory,it lists the "InetMgr.exe" there.
This may not be the problem with Get-ChildItem or the Alias you created but instead with ur IIS Server.

Creating an executable .exe file from a PowerShell Script?

Is it possible to create an executable file.exe file from a PowerShell Script?
No. At least, not yet, and after 5 versions of PowerShell, it seems unlikely ever.
I wish I could just leave it at that, but other people have provided a bunch of "workaround" type answers I feel compelled to address:
You can wrap your .ps1 script in another script type to make it double-clickable, and you can even generate an executable with the script embedded (see the other answers on this thread) ... but those "executables" require the right version of PowerShell to be already present on the system, so you're not gaining anything by doing that, and you loose a lot of the features of PowerShell (like streaming object output, help documentation, and automatic parameter handling with tab completion for users).
Here is a simple .cmd batch file wrapper (you could extend this to allow parameters):
REM <#
copy %0 %0.ps1
PowerShell.exe -ExecutionPolicy Unrestricted -NoProfile -Command "&{Set-Alias REM Write-Host; .\%0.ps1}"
del %0.ps1
exit
REM #>
### Your PowerShell script goes below here.
### I've put a couple of lines as an example ...
ls | sort length -desc | select -first 5 | ft
ps | sort ws -desc | select -first 10 | ft
I know ...
With Portable PowerShell, it would probably be possible to package up a sort of self-extracting zip that would contain the right version of PowerShell and a script and would work. That's not an executable in any normal sense of the word -- it's a bit like if Valve had decided to just ship a vmware image on a thumbdrive as their solution to letting Linux users play Half Life. However, the product seems abandoned.
With PrimalScript (or PowerShell Studio) or PowerGui or pShellExec, your script can be encrypted, so it's slightly secured against prying eyes ... but this is basically just obfuscation, and essentially no different than the batch file, and in some ways worse.
Out of the box - no. However I have built a PowerShell script that can take a script and create an EXE wrapper around it. I created this script a while ago but decided to blog it here for folks to check out.
Use PowerGUI's Script Editor (it is free and works). Open your script in the PowerGUI Script Editor > Tools > Compile script > Choose whatever options you would like for your .exe (password protect source code, automatically close console after .exe runs, etc.).
Yes, there is a option with PS2EXE to create such *.exe Files.
Usage
The whole thing is really simple and well explained nevertheless
here is a snippet of it:
C:\Scripts\PS2EXE\PS2EXE_0.5.0.0.0\ps2exe.ps1
-inputFile C:\Scripts\ExampleEXE\example.ps1
-outputFile C:\Scripts\ExampleEXE\example.exe -sta -noConsole -runtime40 -verbose -x64
The only bad thing is that the project is depreciated. No Updates or new Versions since 2015.
EDIT:
This projected has been picked up and is being maintained by a new person now. You can find the updated code here, last updated 01/04/2018 as of this edit.
https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-GUI-Convert-e7cb69d5
Version Information
For adding and editing the version information use something like VERPATCH.
UPDATE 2019
Shout out to a git-repo which is called PythonEXE.
It demonstrates how to create an executable from a Python project and also provides a YouTube Step-By-Step Guide.
I understood your question as "Can my PowerShell script generate an executable?" That is what I was trying to do when I found this post. That is possible using the Add-Type command.
Add-Type -TypeDefinition #"
using System;
class Program {
public static void Main(string[] args) {
Console.WriteLine("Hello World!");
}
}
"# -CompilerParameters #{
"GenerateExecutable" = $true
"OutputAssembly" = "test2.exe"
}
PrimalScript from Sapien will generate an exe from a PowerShell script. The machine one which the executable is run must have PowerShell installed.
The solution I found best to distribute a PowerShell script as exe was to wrap it in a NSIS executable.
I write a .nsi script like this:
Name "Maintenance task"
OutFile "maintenance.exe"
ShowInstDetails show
Section "Main"
;Executes the "script-to-run.ps1" PowerShell script
InitPluginsDir
SetOutPath "$pluginsdir\MyOrg" ;It is better to put stuff in $pluginsdir, $temp is shared
;extract the .ps1 and run it, collecting output into details.
File script-to-run.ps1
nsExec::ExecToLog 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "$pluginsdir\MyOrg\script-to-run.ps1" '
SetOutPath $exedir
SectionEnd
I just have to compile the script to an exe with the NSIS toolchain, and it will run on any OS that has PowerShell, no matter what is the execution policy.
This was inspired by this question How to call PowerShell in NSIS.
There's a project called Portable PowerShell that is still in beta after a couple of years ... might be worth looking at for your needs.
http://shelltools.wik.is/Portable_PowerShell

how to edit a file in powershell remoting session (powershell)

I am connecting to another computer using powershell remoting, really nice. can do lots, but how do I edit a file?
PS C:\Users\guutlee> Enter-PSSession -ComputerName appprod
[appprod]: PS C:\Users\guutlee\Documents> cd \myapp
[appprod]: PS C:\myapp>
what can I do to open a file editor on a file on the remote machine?
[appprod]: PS C:\myapp> edit app.config
so edit "filename" just seems to hang, from powershell.exe or from powershell_ise.exe
The only thing I can think of is back out of the pssession and "start \webprod\c$\inetpub\myapp\web.config", which would open visual studio.
[appprod]: PS C:\myapp> exit
PS C:\Users\guutlee> start \agobuild\c$\myapp\app.config
PS C:\Users\guutlee> Enter-PSSession -ComputerName appprod
[appprod]: PS C:\Users\guutlee\Documents> cd \myapp
[appprod]: PS C:\myapp> myapp.exe
Of course with this I have to re-find the file, hope that the c$ share is available and accessible, and the reconnect my pssession and re-find my working directory when I want to go on. It doesn't seem very elegant.
I could maybe wrap this is a function, but having a hard time wrapping my head around that..
so how do I conveniently edit a file with a remote pssession?
EDIT
kbrimington's post got me thinking me about the -X option to ssh. probably would be an awesome thing for powershell sessions to be able to forward windowed apps back to the original windowing environment...
but still I'd be happy just to edit the file.
EDIT
tests using vi, emacs, cmd and edit
PS C:\Users\Meredith> Enter-PSSession -ComputerName appprod
[appprod]: PS C:\Users\guutlee\Documents> C:\vim\vim72\vim filename.txt
[appprod]: PS C:\Users\guutlee\Documents> C:\emacs-23.2\bin\emacs.exe -nw filename.txt
emacs.exe : emacs: standard input is not a tty
+ CategoryInfo \: NotSpecified: (emacs: standard input is not a tty:String) [], RemoteException
+ FullyQualifiedErrorId \: NativeCommandError
[appprod]: PS C:\Users\guutlee\Documents> cmd
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\guutlee\Documents>
[appprod]: PS C:\Users\guutlee\Documents> edit filename.txt
vi and edit hang (Control-C to get a prompt back)
cmd runs, producing a prompt, but immediately exits back to the powershell prompt
emacs produces the error (standard input is not a tty)
EDIT
Jered suggests pulling the file back locally to edit. I embellished his answer to copying using pssessions rather than UNCs (perhaps this is what he intended)
PS C:\Users\Meredith> Invoke-Command -Session $ps -ScriptBlock {get-content c:/inetpub/myapp/web.config} > web.config
edit web config
PS C:\Users\Meredith> get-content web.config | Invoke-Command -Session $ps -ScriptBlock {set-content c:/inetpub/myapp/web.config}
Potentially we could run the invoke-commands in either direction, local to remote or remote back to local.
If you are using Powershell 5, you can use command called PSEdit. It only works from ISE.
So first, open PowerShell ISE
Then open remote session to the remote computer using Enter-PSSession
Then edit the file using PsEdit 'filename'
The remote file will be opened in a new tab in your (local) ISE window.
Actually I found this answer from the comments section of this SO question , but I think it will be helpful for others if I post it as answer here.
Can you not pull the file locally, edit it and post it? I know this is tedious and not elegant but it seems editors are presently having issue with remote sessions.
E.g.,
Get-Content REMOTE\Filename.txt > LOCAL\Filename.txt
Make your changes locally and then
Set-Content -path REMOTE\Filename.txt -value (get-content LOCAL\Filename.txt)
EDIT
Also if you are only replacing certain instances you can do this pretty easily.
E.g.,
Get-Content REMOTE\Filename.txt | foreach-object { $_ -replace "OLD", "NEW" } | Set-Content REMOTE\Filename.txt
After much digging around, I found something that seems relevant in the powershell help documentation. At the powershell prompt, type:
help about_remote_troubleshooting
At the very end of the help file that is displayed, there is a section entitled 'TROUBLESHOOTING UNRESPONSIVE BEHAVIOUR', which states:
TROUBLESHOOTING UNRESPONSIVE BEHAVIOR
This section discusses remoting problems that prevent a command from
completing and prevent or delay the return of the Windows PowerShell
prompt.
HOW TO INTERRUPT A COMMAND
Some native Windows programs, such as programs with a user interface,
console applications that prompt for input, and console
applications that use the Win32 console API, do not work
correctly in the Windows PowerShell remote host.
When you use these programs, you might see unexpected behavior, such
as no output, partial output, or a remote command that does not
complete. To end an unresponsive program, type CTRL + C. To view any
errors that might have been reported, type "$error" in the
local host and the remote session.
Thus it would seem even non-GUI console applications such as VIM won't work unfortunately. Anyone
care to shed a little light on why this might be the case and/or whether it can be worked
around? I would REALLY love it if I could use vim over powershell remoting.
First, create a temp folder on the local machine (LOCALTEMPFOLDER). Then, use the following function:
function vimrem {param([parameter(position=0,mandatory=$true)][string]$Session, [parameter(position=1,mandatory=$true)][string]$Path)
$TempFile = split-path -path $Path -leaf
copy-item -fromsession $Session -path $Path -destination LOCALTEMPFOLDER\$TempFile
vim $LOCALTEMPFOLDER\$TempFile
copy-item -tosession $Session -path LOCALTEMPFOLDER\$TempFile -destination $Path
remove-item -path LOCALTEMPFOLDER\$TempFile
}
This should work, but you will have leave an interactive session before using this function.
PowerShell_ISE.exe \\REMOTE\...\File.txt
will load and edit the file directly and save it back to the remote computer in one step and, since its command line, easy to build functions using it. Doesn't get around sharing problems, but the easiest way I've found.
Try it out using a console-based editor such as VI or Emacs. As in my comment, I think the problem is that the edit command is bound to a windowed application which, in turn, is not virtualized across a remote session.
I try all the above suggestion and even other microsoft related solution but none works the way you and I want --"full interactive and responsive shell"--. If you really want to have the ssh experience that unix users have from the beggining of time i recomend you install an ssh server. I personally use freesshd, you can find it here http://www.freesshd.com and instructions of how to configure it here http://www.windowsnetworking.com/articles_tutorials/install-SSH-Server-Windows-Server-2008.html. After you make all that it says in the instructions you only need to use any ssh client app to connect to your computer and use powershell full interactive. Vim, edit, emacs or whatever you use to edit a file is going to work without any problem.
i encourage you to not waste your time with psremoting, telnet, winrs, psexec, trying to achieve what a real interactive shell provide (i already lost it, T_T). Try that ssh server an see for your self.
Inspired by the answer provided by #chenz, this can also be done using Visual Studio Code when inside the Powershell Integrated Shell. I tried this with Powershell 7 over SSH remoting, but should also work with WinRM remoting as well.
Enter-Session ...
[RemoteSystem] PS> psedit service.log
The filename will follow this pattern:
C:\users\dev\appdata\local\temp\2\pses-15960\remotefiles\1702137071\winboxname\service.log
I got nano to work easily over SSH to PowerShell. It's available in Chocolatey so you can just do...
choco install nano -y
Then you can just do...
nano filename
I've been looking into this quite thoroughly given the limitations of PSRemoting and the possible work arounds or solutions.
Console editors do not work as they are native (exe) commands and are character based. (I'm wondering if cmd over ssh works with these) It needs to be a cmdlet to properly interact with the console host over a psremote session.
A PSRemote session is line based. You edit the line locally push enter and then it is sent to the remote end, the command is executed and the result returned. So it does support line interactivity but not character interactivity.
Given all these limitations, GNU's ed appears to be a perfect fit. I'm surprised that no one has looked at implementing it as a cmdlet.
I decided to investigate this further, I checked that the powershell cmdlet read-host works and then the C# equivalent PSHostUserInterface.ReadLine() work over a PSRemote session and they do, which is all that is needed to make a working line editor.
So here's what I've done so far. I could probably use some help on the more exotic regex code.
https://github.com/silicontrip/ps-ed
I've used this to edit files via a psremote session. (I wouldn't go editing large source files with it, but for the odd small config file or ps1 script it is perfect.)
Make sure you are familiar with GNU ED before using this cmdlet. It'd be like trying to use VI for the very first time, otherwise.