Коды символов

powershell remove characters from string

String manipulation is an integral part of PowerShell scripting. When working with string data in PowerShell, you may need to remove certain characters like spaces, newlines, brackets, or even entire substrings from a string. PowerShell provides a wide range of techniques to delete characters from strings efficiently. These include removing characters from the start of a string, removing the first-last character from a string, numbers, quotes, white spaces, special characters, and substrings from a string.

In this beginner’s guide, we’ll focus on each of these scenarios and provide step-by-step instructions on removing characters from strings in PowerShell scripts. Whether you’re an expert seeking a refresher or a beginner trying to get a foothold, this post is for you!

Common scenarios for removing characters from a string in PowerShell

  • Remove spaces, tabs, and newlines to consolidate text
  • Delete quotation marks for cleaner output
  • Strip brackets or parenthesis when extracting text segments
  • Trim leading/trailing characters like – or @ from strings
  • Clean invalid characters for file naming or passwords
  • Standardize formatting by deleting excess characters
  • Shorten strings by removing unnecessary sections

PowerShell makes it quick and easy to sanitize strings by removing specific characters. Let’s look at some examples of the common scenarios and techniques for removing characters from a string in PowerShell.

Removing All spaces from a string in PowerShell

$originalString = "Hello, World!"
$modifiedString = $originalString.Replace(" ", "")

In this example, $modifiedString will store the new string value “Hello,World!” with all spaces removed. The -replace operator deletes all matches of the space character in the string.

Let’s see another example: Suppose you are automating the process of saving files, and you want to ensure that filenames don’t contain spaces (which can sometimes cause problems, especially in URLs or certain file systems).

$FileName = "Quarterly Report Q1 2023.docx"
$CleanedFilename = $Filename -replace ' ', ''
Write-Output $CleanedFilename
PS C:\> $FileName = "Quarterly Report Q1 2023.docx"
PS C:\> $CleanedFilename = $Filename -replace ' ', ''
PS C:\> Write-Output $CleanedFilename
QuarterlyReportQ12023.docx
PS C:\>

Trimming white spaces in a string

If you have trailing spaces at the end of a string that needs to be removed, you can use the TrimEnd() method in PowerShell. This method removes all occurrences of a specified set of characters from the end of a string. Here’s an example:

$originalString = "Hello, World! "
$modifiedString = $originalString.TrimEnd()

In this example, the $modifiedString variable will contain the value "Hello, World!", as the trailing spaces have been removed from the original string. Similarly, to trim white spaces at the start of the string, use TrimStart() method:

$originalString = " Hello, World!"
$modifiedString = $originalString.TrimStart()

If you want to trim both leading and trailing spaces, use PowerShell trim method:

$originalString = " Hello, World! "
$modifiedString = $originalString.Trim()

This will remove the starting and ending whitespace and output: Hello, World!

The Trim method can also remove an array of characters from a string. Say, for example, let’s remove the extension from a file name.

$FileName = "Database-Backup-Jan2022.bak"
$Filename.Trim(".bak")
#Result: Database-Backup-Jan2022

Here is another script to loop through all files in a folder and remove extensions from file names:

# Remove Extention from File Names
Get-ChildItem "C:\Temp" -File | ForEach-Object { $_.name -replace "(\.\w+)$", "" }

Replace two or more spaces with a single space

If you want to replace occurrences of two or more spaces with a single space in a string using PowerShell, you can utilize the -replace operator with a regular expression patterns and wildcards. Here’s an example script to demonstrate:

$string = "This is a string with multiple spaces."
# Replace two or more spaces with a single space
$cleanedString = $string -replace ' {2,}', ' '
Write-Output $cleanedString

This script will take the variable $string, and any occurrence of two or more spaces will be replaced with a single space. The output for the above example will be: This is a string with multiple spaces.

Removing the first character from a string in PowerShell

Removing the first character from a string in PowerShell can be achieved using the Substring method. By specifying the range from the second character to the end of the string, you exclude the first character. Here’s an example:

$originalString = "#Comment"
$modifiedString = $originalString.Substring(1)

This skips the first character (index 0) and returns the rest of the string. In this example, $modifiedString will store the value “Comment” without the “#” at the beginning.

Remove Prefix from a String

Removing a prefix from a string is a common task in text processing. Here’s how you can do it:

$string = "PREFIX_MainText"
$cleanString = $string.Substring(7)

Useful when you have a known prefix to remove. You can also remove a prefix using the “String.Remove” method of string objects:

$id = "EMP_12345"
$idWithoutPrefix = $id.Remove(0, 4)
Write-Output $idWithoutPrefix

Here is another way to remove a prefix from a string:

$productCode = "US-12345-US2025"
$standardizedCode = $productCode -replace '^US-', ''
Write-Output $standardizedCode
#Output: 12345-US2025

This removes only the given substring from the prefix part of the string. The ^ character ensures that the pattern matches only at the beginning of the string (i.e., a prefix).

Removing the last character from a string in PowerShell

To remove the last character from a string in PowerShell, you can utilize the Substring method, along with the Length property. By specifying the range from the start of the string to the length minus one, you effectively discard the last character. Here’s an example:

$originalString = "Hello World!"
$modifiedString = $originalString.Substring(0, $originalString.Length - 1)

By grabbing from index 0 to one less than the total length, the last character is omitted. In this example, $modifiedString will store the value “Hello World” without the exclamation mark at the end. Similarly, you can remove the last characters from a string using regular expressions:

$string = "Example!"
$newString = $string -replace '.$'
Write-Output $newString
#Output: Example

Removing a specific number of characters from the end

In some cases, you may need to remove a specific number of characters from the end of a string. PowerShell provides the Substring method to achieve this. By specifying the starting index as 0 and the length as the original length minus the desired number of characters, you can remove characters from the end. Here’s an example:

$FileName = "Database-Backup-Jan2022.bak"
$BaseName = $FileName.Substring(0, $FileName.Length - 4)
$BaseName

In this example, $BaseName will store the value “Database-Backup-Jan2022” with the last 4 characters removed.

Removing specific characters from a string in PowerShell

To remove specific characters from a string in PowerShell, you can use the Replace method. This method allows you to replace occurrences of a specified character or substring with another value or simply remove them. Here’s an example:

$originalString = "Hello World!"
$modifiedString = $originalString.Replace("o", "")

In this example, $modifiedString will store the value “Hell Wrld!” with all occurrences of the letter “o” removed. Similarly, if you want to remove multiple characters from a string, use:

$string = "abcdef"
$modifiedString = $string -replace '[bdf]', ''
$modifiedString

Output: ace. Please note that the “-replace” operator is case-insensitive by default. If you want to perform case sensitive replace, use: creplace operator.

Removing characters from the start of a string

To remove characters from the start of a string in PowerShell, you can use the Substring() method. This method allows you to extract a portion of a string starting from a specified index. By specifying an index greater than zero, you can effectively remove characters from the start of the string. Here’s an example:

$originalString = "Hello, World!"
$modifiedString = $originalString.Substring(5)

In this example, the $modifiedString variable will contain the value "o, World!", as the first five characters have been removed from the original string.

Removing the first and last character from a string

There may be situations where you need to remove both the first and last characters from a string in PowerShell. To achieve this, you can combine the Substring() method with the Length property of a string. Here’s an example:

$originalString = "#Hello World#"
$modifiedString = $originalString.Substring(1, $originalString.Length-2)

In this example, the $modifiedString variable will contain the value "Hello World", as the first and last characters have been removed from the original string. Here is another example:

$string = "<tag>"
$cleaned = $string.Substring(1, $string.Length - 2)

This is useful for specific data formats.

Removing special characters from a string in PowerShell

Special characters can often interfere with data processing or cause unexpected behavior. To remove special characters from a string in PowerShell, you can use regular expressions combined with the Replace function. Here’s an example:

$originalString = "Hello #World!"
$modifiedString = [regex]::Replace($originalString, "[^a-zA-Z0-9\s]", "")

To strip all special characters other than non-alphabetic characters from a string, You can also use the PowerShell replace operator:

$originalString -replace "[^\w\s]",""
$html = "<p>Hello <b>World</b></p>"
#Remove tags from text
$text = $html -replace "<.*?>",""

Removing Specific special characters from a string

To remove special characters from a string in PowerShell, you can use the Replace() method and specify the characters you want to remove. You can create a string containing all the special characters you want to remove and pass it as the first argument to the Replace() method. Here’s an example:

$originalString = "Hello, $@Wor#ld!"
$specialCharacters = "[$@#]"
$modifiedString = $originalString -replace $specialCharacters, ""

Here is another example of removing a specific special character’s two or more instances:

$Text = "Hey!! How have you been???"
$QuestionmarkTrimmed = $Text -replace '(\?)+', '?'
$ExclamationTrimmed = $QuestionmarkTrimmed -replace '(!)+', '!'
$ExclamationTrimmed

In this example, the -replace operator with regex patterns (!)+ and (\?)+ captures instances where there are multiple exclamation marks or question marks consecutively. It then replaces these occurrences with a single exclamation mark or question mark, respectively.

:/>  Как перезагрузить ноутбук с помощью клавиатуры

Removing Currency Symbols from Prices:

$prices = @("$100", "£150", "€200")
foreach ($price in $prices) { $cleanedPrice = $price -replace '[$£€]', '' Write-Output $cleanedPrice
}

Removing specific patterns or formats from a string in PowerShell

Sometimes, you may need to remove specific patterns or formats from a string. PowerShell’s regular expression capabilities can be leveraged to achieve this. By using the -replace operator and specifying a regular expression pattern, you can remove matching substrings from a string. Here’s an example:

$string = "This is a [sample] text."
$withoutBrackets = $string -replace '\[|\]', ''
$withoutBrackets

This PowerShell script removes brackets from a string. What if you want to remove brackets and everything inside the brackets?

$originalString = "Hello [World]!"
$modifiedString = $originalString -replace "\[.*?\]"

In this example, $modifiedString will store the value “Hello !” with the square brackets removed.

Removing numbers from a string

If you need to remove numbers from a string in PowerShell, you can use regular expressions. Regular expressions are patterns used to match and manipulate text. You can leverage the Replace() method and specify a regular expression pattern to remove numbers from a string. Here’s an example:

$OriginalString = "abc123def456"
$ModifiedString = $originalString -replace "\d", ""

In this example, the $modifiedString variable will contain the value "abcdef", as all numbers have been removed from the original string. Alternatively, you can use:

$String = "Hello123"
$stringWithoutNumbers = $string -replace '[0-9]', ''
$stringWithoutNumbers

How about the opposite? Removing everything other than numbers from a string?

$text = "Call me at 555-1234 for assistance."
$phone = ($text -replace "[^\d]","")
$phone

Removing Leading Zeros from Numbers:

$numbers = @("00123", "0456", "007890")
foreach ($number in $numbers) { $cleanedNumber = $number -replace '^0+', '' Write-Output $cleanedNumber
}

This can be handy if you’re working with numeric strings that may have unnecessary leading zeros:

Removing quotes from a string

When extracting text from documents or code, surrounding quotes may be included unintentionally. To remove quotes from a string in PowerShell, you can use the Replace() method and specify the quotation marks as the characters to be replaced. Here’s an example to remove single quotes from a string:

$originalString = "'Hello, World!'"
$modifiedString = $originalString.Replace("'", "")

In this example, the $modifiedString variable will contain the value "Hello, World!", as the quotes have been removed from the original string. Similarly, to remove double quotes from a string, use:

$originalString = '"Acme Inc","500","True"'
$modifiedString = $originalString -replace '"',""
$modifiedString

By stripping the double-quote marks, you’re left with values: Acme Inc,500,True

Removing a substring from a string

To remove a specific substring from a string in PowerShell, you can use the Replace() method and specify the substring you want to remove. Here’s an example:

$originalString = "This text contains too sensitive data"
$modifiedString = $originalString -replace " too sensitive",""
$modifiedString

In this example, the $modifiedString variable will contain the value "This text contains data!", as the substring ” too sensitive” has been removed from the original string.

Search and Remove Substring from String

The Remove method deletes a specified number of characters from the current string, starting from a specified position. Suppose you have a filename, and you want to get just the name without the extension:

$FileName = "Document.docx"
$NameWithoutExtension = $Filename.Remove($FileName.LastIndexOf('.'))
Write-Output $NameWithoutExtension
$logEntry = "User email: john.doe@example.com Logged in"
$atIndex = $logEntry.IndexOf("@")
$endOfEmail = $logEntry.IndexOf(" ", $atIndex) # finding the space after the '@'
$sanitizedLog = $logEntry.Remove($atIndex, $endOfEmail - $atIndex)
Write-Output $sanitizedLog

Removing Brackets and Parentheses from a string

To remove specific special characters, such as Brackets and Parentheses, from a string in PowerShell, you can use the Replace method. By specifying the character or substring to be replaced, you can effectively remove them from the string. Here’s an example:

$originalString = "Believer [Official Audio] (2017).mp3"
$modifiedString = $originalString.Replace("[", "").Replace("]", "")

In this example, $modifiedString will store the value “Hello World!” with all brackets removed.

Stripping Backslashes from strings and File Paths

When working with Windows file paths, you may want to standardize slashes:

$FilePath = "C:\Users\\John\Documents\\File.txt"
# Replace double backslashes with a single slash
$Filepath -replace '\\\\', '\'

This replaces any double backslashes with a single slash for cross-platform consistency.

Removing carriage returns and line breaks from a string in PowerShell

Newlines and carriage returns can cause strings to span multiple lines unexpectedly. If you need to remove carriage returns and line breaks from a string in PowerShell, you can use the Replace method along with the appropriate escape sequences. By replacing the escape sequences with an empty string, you effectively remove them from the string. Here’s an example:

$originalString = "Hello`r`nWorld!"
$modifiedString = $originalString.Replace("`r`n", "")

In this example, $modifiedString will store the value “HelloWorld!” with the carriage return and new lines removed.

remove new line character from string in powershell

Best practices and tips for efficient string manipulation in PowerShell

When working with string manipulation in PowerShell, there are a few best practices and tips to keep in mind:

  1. Use the appropriate method or operator for the specific scenario to achieve optimal performance.
  2. Consider using regular expressions for complex pattern matching and removal.
  3. Test your code with different input scenarios to ensure it handles edge cases correctly.
  4. Document your code and provide meaningful variable names for easier maintenance.
  5. Utilize PowerShell’s built-in string manipulation functions and methods to simplify your code.

Wrapping up

In this article, we explored various techniques for efficiently removing characters from a string in PowerShell. We covered scenarios such as removing the last or first character, removing specific characters or substrings, removing spaces and special characters, and more.

Here is my other post for replacing strings in PowerShell: Replace String in PowerShell: A Comprehensive Guide

How to remove backslash from string in PowerShell?

To remove backslashes from a string in PowerShell, you can use the Replace() method. Here’s an example:
$string = "Hello\World"
$string.replace("\", " ")

How to remove non-alphanumeric characters from string in PowerShell?

How do I remove spaces from beginning and end of string in PowerShell?

To remove whitespace from a PowerShell string, you can use the Trim() method. This method removes any leading and trailing whitespace from the string. Here’s an example:
$string = " Hello World "
$string = $string.Trim()

How to remove part of string in PowerShell?

To remove a specific part of a string in PowerShell, you can use the Replace() method or the -replace operator. Here is an example of how to do it:
$string = "Hello World"
$string = $string -replace " World", ""

$string = "Hello World"
$string = $string.replace(" World", "")

How do you replace all occurrences of a string in PowerShell?

To replace all occurrences of a string in PowerShell, the -replace operator or replace() method works. Here is an example:
$string = "Hello World"
$string = $string -replace "o", "i"

Output: Helli Wirld

How do I remove the first 5 characters from a string?

How do I remove a character from an array in PowerShell?

How do I remove a character from a text file in PowerShell?

How do I remove specific characters from a string using PowerShell?

Install/uninstall driver

Working with drivers is not something to be worried about. Although the MSI technology does not offer a native way via the database tables that you can use, the OS is offering multiple choices for you to achieve this goal.

Let’s have a look at how you can install drivers with MSI by taking different approaches.

DPInst

Driver Package Installer (DPInst)is a component of Driver Install Frameworks (DIFx) version 2.1. DIFx simplifies and customizes the installation of driver packages for devices that you wish to install on the computer. This type of installation is commonly known as a software-first installation. DPInst also automatically updates the drivers for any installed devices that are supported by the newly installed driver packages.

DPInst searches for INF files for driver packages in the DPInst working directory which by default is the DPInst root directory, which is the directory that contains the DPInst executable (DPInst.exe).

You can also use the /path command-line switch to specify a custom DPInst working directory.

The log files for the DPInst utility can be found in the %SystemRoot%\DPInst.log. However, DPInst does not come natively with the OS and must be added into the MSI package, preferably near the driver .inf files.

PnPUtil

PNPUtil.exe /add-driver PATH\DRIVERNAME.inf /install

Now that we know two methods which we can use to install the drivers, let’s see how we can use them in VBScript or PowerShell.

Installing drivers with VBScript

Let’s take a look at both utility tools and create the necessary scripts to install a driver. Let’s assume that the driver .inf name is HP.inf. Also, let’s assume that we are going to place the DPInst.exe utility directly into the C:\Windows\DPInst folder and there we are going to place the .inf file as well.

The script to install the driver is:

Option Explicit
On Error Resume Next
Dim strCmd,WshShell,strInstalldir
Set WshShell = CreateObject("WScript.Shell")
strInstalldir = WshShell.ExpandEnvironmentStrings( "%SYSTEMROOT%" )
strCmd = chr(34) & strInstalldir & "\DPInst\DPInst_x64.exe" & chr(34) & " /F /LM /S"
WshShell.Run strCmd
Set WshShell = Nothing
  • Option Explicit: Enables explicit variable declaration, ensuring that all variables are declared before use.
  • On Error Resume Next: Instructs the script to continue execution even if an error occurs.
  • Dim strCmd, WshShell, strInstalldir: Declares variables to hold the command, Windows Script Host Shell object, and the installation directory.
  • Set WshShell = CreateObject(“WScript.Shell”): Creates an instance of the Windows Script Host Shell object.
  • strInstalldir = WshShell.ExpandEnvironmentStrings(“%SYSTEMROOT%”): Retrieves the path of the Windows installation directory using the %SYSTEMROOT% environment variable.
  • strCmd = chr(34) & strInstalldir & “\DPInst\DPInst_x64.exe” & chr(34) & ” /F /LM /S”: Constructs the command to be executed. It combines the installation directory path with the relative path to the “DPInst_x64.exe” executable. The /F, /LM, and /S are command-line switches or parameters for the executable.
  • WshShell.Run strCmd: Runs the command stored in strCmd using the Run method of the Windows Script Host Shell object. This executes the DPInst_x64.exe installer with the specified command-line switches.
  • Set WshShell = Nothing: Releases the reference to the Windows Script Host Shell object.
:/>  Как открыть управление дисками в Windows 10 способов?

In summary, the script runs the DPInst_x64.exe installer, located in the DPInst subfolder under the Windows installation directory, with the command-line switches /F, /LM, and /S. The purpose and functionality of the DPInst_x64.exe installer may depend on the specific software or device driver being installed.

The script to uninstall the driver is:

Option Explicit
On Error Resume Next
Dim strCmd,WshShell,strInstalldir,strcmd1, strcmd2
Set WshShell = CreateObject("WScript.Shell")
strInstalldir = WshShell.ExpandEnvironmentStrings( "%SYSTEROOT%" )
strcmd= chr(34) & strInstalldir & "\DPInst\DPInst_x64.exe" & chr(34) & " /S /U " & chr(34) & strInstalldir & "\DPInst\HP.inf" & chr(34) &" /D"
WshShell.Run strCmd
Set WshShell = Nothing
  • Option Explicit: Enables explicit variable declaration, ensuring that all variables are declared before use.
  • On Error Resume Next: Instructs the script to continue execution even if an error occurs.
  • Dim strCmd, WshShell, strInstalldir, strCmd1, strCmd2: Declares variables to hold the commands, Windows Script Host Shell object, and the installation directory.
  • Set WshShell = CreateObject(“WScript.Shell”): Creates an instance of the Windows Script Host Shell object.
  • strInstalldir = WshShell.ExpandEnvironmentStrings(“%SYSTEROOT%”): Retrieves the path of the Windows installation directory using the %SYSTEROOT% environment variable.
  • strCmd = chr(34) & strInstalldir & “\DPInst\DPInst_x64.exe” & chr(34) & ” /S /U ” & chr(34) & strInstalldir & “\DPInst\HP.inf” & chr(34) &” /D”: Constructs the command to be executed. It combines the installation directory path with the relative paths to the “DPInst_x64.exe” executable and “HP.inf” file. The /S, /U, and /D are command-line switches or parameters for the executable.
  • WshShell.Run strCmd: Runs the command stored in strCmd using the Run method of the Windows Script Host Shell object. This executes the DPInst_x64.exe installer with the specified command-line switches and the “HP.inf” file for driver uninstallation.
  • Set WshShell = Nothing: Releases the reference to the Windows Script Host Shell object.

Once we have the scripts done and the DPInst utility downloaded, open Advanced Installer and first navigate to the Files and Folders Page. In here, create a new directory under Windows Volume\Windows called DPInst and add the DPInst utility with the HP.inf file near it.

add the DPInst utility with the HP.inf

Next, navigate to the Custom Actions Page and add the Launch attached file predefined custom action into the sequence, select the installation vbscript file that was previously created and configure the Custom Action as such:

add the Launch attached file predefined custom action

uninstall script and configure the custom action

And that is it, build your package and install it and the driver will appear as installed.

If we don’t want to use the DPInst method and want to go with the PnPUtil one, the VBScript for installation should look like this:

Option Explicit
On Error Resume Next
Dim strCmd,WshShell,strInstalldir,strcmd1, strcmd2
Set WshShell = CreateObject("WScript.Shell")
strInstalldir = WshShell.ExpandEnvironmentStrings( "%SYSTEROOT%" )
strcmd= "pnputil.exe /add-driver " & chr(34) & strInstalldir & "\DPInst\HP.inf" & chr(34)
WshShell.Run strCmd
Set WshShell = Nothing
  • Option Explicit: Enables explicit variable declaration, ensuring that all variables are declared before use.
  • On Error Resume Next: Instructs the script to continue execution even if an error occurs.
  • Dim strCmd, WshShell, strInstalldir, strCmd1, strCmd2: Declares variables to hold the commands, Windows Script Host Shell object, and the installation directory.
  • Set WshShell = CreateObject(“WScript.Shell”): Creates an instance of the Windows Script Host Shell object.
  • strInstalldir = WshShell.ExpandEnvironmentStrings(“%SYSTEROOT%”): Retrieves the path of the Windows installation directory using the %SYSTEROOT% environment variable.
  • strCmd = “pnputil.exe /add-driver ” & chr(34) & strInstalldir & “\DPInst\HP.inf” & chr(34): Constructs the command to be executed. It combines the pnputil.exe utility command /add-driver with the path to the “HP.inf” file for driver installation. The chr(34) is used to enclose the path in double quotes.
  • WshShell.Run strCmd: Runs the command stored in strCmd using the Run method of the Windows Script Host Shell object. This executes the pnputil.exe utility with the /add-driver command and the specified driver inf file for installation.
  • Set WshShell = Nothing: Releases the reference to the Windows Script Host Shell object.

The script to remove the driver with PnPUtil is:

Option Explicit
On Error Resume Next
Dim strCmd,WshShell,strInstalldir,strcmd1, strcmd2
Set WshShell = CreateObject("WScript.Shell")
strInstalldir = WshShell.ExpandEnvironmentStrings( "%SYSTEROOT%" )
strcmd= "pnputil.exe /delete-driver " & chr(34) & strInstalldir & "\DPInst\HP.inf" & chr(34)
WshShell.Run strCmd
Set WshShell = Nothing
  • Option Explicit: Enables explicit variable declaration, ensuring that all variables are declared before use.
  • On Error Resume Next: Instructs the script to continue execution even if an error occurs.
  • Dim strCmd, WshShell, strInstalldir, strCmd1, strCmd2: Declares variables to hold the commands, Windows Script Host Shell object, and the installation directory.
  • Set WshShell = CreateObject(“WScript.Shell”): Creates an instance of the Windows Script Host Shell object.
  • strInstalldir = WshShell.ExpandEnvironmentStrings(“%SYSTEROOT%”): Retrieves the path of the Windows installation directory using the %SYSTEROOT% environment variable.
  • strCmd = “pnputil.exe /delete-driver ” & chr(34) & strInstalldir & “\DPInst\HP.inf” & chr(34): Constructs the command to be executed. It combines the pnputil.exe utility command /delete-driver with the path to the “HP.inf” file for driver deletion. The chr(34) is used to enclose the path in double quotes.
  • WshShell.Run strCmd: Runs the command stored in strCmd using the Run method of the Windows Script Host Shell object. This executes the pnputil.exe utility with the /delete-driver command and the specified driver inf file for deletion.
  • Set WshShell = Nothing: Releases the reference to the Windows Script Host Shell object.

Do the same steps as we did before to add the VBScript files in the custom actions, build the installer and the driver should get installed.

Installing drivers with PowerShell

Let’s assume that the driver .inf name is HP.inf. Also, let’s assume that we are going to place the DPInst.exe utility directly into the C:\Windows\DPInst folder and there we are going to place the .inf file as well.

The script to install the file as we did with VBScript is:

$DPInstLoc = $env:SystemRoot + "\DPInst\DPInst_x64.exe"
$cmd = "$DPInstLoc /F /LM /S"
Invoke-Expression $cmd
  • $DPInstLoc = $env:SystemRoot + “\DPInst\DPInst_x64.exe”: Sets the variable $DPInstLoc to the path of the DPInst_x64.exe file located in the %SystemRoot%\DPInst directory. The $env:SystemRoot environment variable represents the path to the Windows installation directory.
  • $cmd = “$DPInstLoc /F /LM /S”: Constructs a command string that includes the value of $DPInstLoc and additional command-line arguments. In this case, the command is DPInst_x64.exe /F /LM /S. The /F switch specifies that existing driver packages should be deleted, /LM specifies that the driver should be installed for all users on the local machine, and /S enables silent installation without displaying any user interface.
  • Invoke-Expression $cmd: Executes the command stored in the $cmd variable using the Invoke-Expression cmdlet. This cmdlet interprets and runs the command as if it were typed directly into the PowerShell console.

The script to uninstall the driver is:

$DPInstLoc = $env:SystemRoot + "\DPInst\DPInst_x64.exe"
$INFLocation = $env:SystemRoot + "\DPInst\HP.inf"
$cmd = "$DPInstLoc /S /U $INFLocation"
Invoke-Expression $cmd
  • $DPInstLoc = $env:SystemRoot + “\DPInst\DPInst_x64.exe”: Sets the variable $DPInstLoc to the path of the DPInst_x64.exe file located in the %SystemRoot%\DPInst directory. The $env:SystemRoot environment variable represents the path to the Windows installation directory.
  • $INFLocation = $env:SystemRoot + “\DPInst\HP.inf”: Sets the variable $INFLocation to the path of the HP.inf file located in the %SystemRoot%\DPInst directory.
  • $cmd = “$DPInstLoc /S /U $INFLocation”: Constructs a command string that includes the values of $DPInstLoc and $INFLocation as well as additional command-line arguments. In this case, the command is DPInst_x64.exe /S /U HP.inf. The /S switch enables silent installation without displaying any user interface, and the /U switch specifies the INF file to be used for uninstallation.
  • Invoke-Expression $cmd: Executes the command stored in the $cmd variable using the Invoke-Expression cmdlet. This cmdlet interprets and runs the command as if it were typed directly into the PowerShell console.

Once we have the scripts done and the DPInst utility downloaded, open Advanced Installer and first navigate to the Files and Folders Page. In here, create a new directory under Windows Volume\Windows called DPInst and add the DPInst utility with the HP.inf file near it.

Next, navigate to the Custom Actions Page and add the Run PowerShell script file predefined custom action into the sequence, select Attached Script and select the file that was previously created and configure the Custom Action as such:

add the Run PowerShell script file predefined custom action

configure the Custom Action

Next, build the package and during installation/uninstallation the PowerShell scripts will run and install/uninstall the driver.

If we are going with the PnPUtil route, the script to install is quite simple:

$DriverPath = $env:windir + "\DPInst"
Get-ChildItem $DriverPath -Recurse -Filter "*inf" | ForEach-Object { PNPUtil.exe /add-driver $_.FullName /install }
  • $DriverPath = $env:windir + “\DPInst”: Sets the variable $DriverPath to the path of the DPInst directory located in the Windows installation directory (%windir%). The $env:windir environment variable represents the path to the Windows directory.
  • Get-ChildItem $DriverPath -Recurse -Filter “*inf”: Retrieves all the files with the “.inf” extension located in the $DriverPath directory and its subdirectories using the Get-ChildItem cmdlet. The -Recurse parameter ensures that files are searched recursively.
  • ForEach-Object { PNPUtil.exe /add-driver $_.FullName /install }: For each “.inf” file found in the previous step, it executes the PNPUtil.exe utility to add and install the driver specified by the $_ variable (represents the current file object). The /add-driver switch is used to add the driver package, and the /install switch is used to install the driver.
:/>  Как удалить программу вин 8 и как ее убрать?

The script to uninstall the driver with PnPUtil is:

$DriverPath = $env:windir + "\DPInst\HP.inf"
$Arguments = "pnputil /delete-driver $DriverPath"
Start-Process -FilePath PowerShell.exe -ArgumentList $Arguments -Wait
  • $DriverPath = $env:windir + “\DPInst\HP.inf”: Sets the variable $DriverPath to the path of the “HP.inf” file located in the DPInst directory within the Windows installation directory (%windir%). The $env:windir environment variable represents the path to the Windows directory.
  • $Arguments = “pnputil /delete-driver $DriverPath”: Sets the variable $Arguments to the command-line arguments that will be passed to the PowerShell process. In this case, it constructs a command to delete the driver specified by the $DriverPath variable using the pnputil utility.
  • Start-Process -FilePath PowerShell.exe -ArgumentList $Arguments -Wait: Starts a new instance of the PowerShell process and passes the $Arguments as command-line arguments. The -Wait parameter ensures that the script waits for the PowerShell process to complete before continuing.

Once we have the scripts we need to do the same steps as we did with the DPInst method and then build and install the package.

Installing drivers with Advanced Installer

Advanced Installer makes it much easier to handle driver operations by providing a simple and intuitive GUI for these actions.

Navigate to the Drivers page and click on New Driver. A window will open for you to select the .inf file which must be present in the package.

select the .inf file

Advanced Installer parses the .INF file and detects what is needed and you have multiple settings to choose from:

parses the .INF file

And that is it, all you have to do is build the MSI and install the package. Simple right?

advanced MSI packaging

MSI Packaging In-Depth Training Book

by Alexandru Marin

Время на прочтение

Коды символов

PowerShell – это средство автоматизации разработанное и выпущенное Microsoft в 2006 году на замену Командной строке и её батникам, помимо всего функционала cmd – Powershell обзавелась собственным скриптовым языком с поддержкой классов, объектов, переменных и т.д. По сути с её помощью можно обращаться ко всему функционалу Windows и Windows Server как к объектам и выполнять с ними действия. В статье я расскажу свой опыт, как автоматизировал создание пользователей в домене из писем-заявок в Outlook на удаленном сервере AD.

Планировщик задач
Планировщик задач

Все запланированные задачи в Windows можно посмотреть в “Планировщике задач”, автоматизировать Windows возможно как с его помощью, так и чисто на Powershell, чтобы вывести все текущие задачи необходимо выполнить:

Get-ScheduledJob 

Чтобы вывести запланированные только с помощью Powershell используется команда ниже, так как задачи созданные в Powershell хранятся в отдельной директории, достаточно их просто прочитать:

Get-ChildItem $HOME\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs

Для создания задания необходимо выполнить следующую команду, в квадратные скобки необходимо передать выполняемый скрипт:

$Условие = New-JobTrigger -Daily -At 12AM
Register-ScheduledJob -Name NewAD_User -ScriptBlock {######} -Trigger $Условие

Рассмотрим как происходит взаимодействие с Outlook, и сразу отмечу что для выполнения действий с почтой, необходимо закрыть открытое приложение, иначе команды не будут выполняться.

#Завершение Outlook
Get-Process | Where-Object {$_.ProcessName -eq "OUTLOOK"} | Stop-Process
Start-Sleep -Seconds 10
# Создание объекта Outlook
$outlook = New-Object -ComObject Outlook.Application
# Получение коллекции папок
$folders = $outlook.Session.Folders.Item("###Ваш адрес почты####").Folders
# Выбор папки "Входящие"
$Входящие = $folders.Item("Входящие")
$Исполнено = $folders.Item("Исполнено")
# Получение последнего письма
$Письма = $Входящие.Items | Sort-Object ReceivedTime -Descending

В данном коде я получаю сортированный по дате список писем из папки “Входящие” и адрес папки “Исполнено” куда я планирую перемещать письма после выполнения скрипта.

foreach ($Письмо in $Письма) {
$lines = $Письмо.Body -split "`n"
#Условие чтения письма
if ($lines[0].Substring(0, 29) -ne "Заявка в IT - Новый сотрудник") {continue}
$Дата_заявки = $lines[0].Substring(32).Trim()
$Фамилия = $lines[2].Substring(18).Trim()
$Имя = $lines[4].Substring(4).Trim()
$Отчество = $lines[6].Substring(9).Trim()
$Отдел = $lines[8].Substring(6).Trim()
$Должность = $lines[10].Substring(10).Trim()
$Организация = $lines[12].Substring(12).Trim()
$Подразделение = $lines[14].Substring(14).Trim()
$Номер_телефона = $lines[16].Substring(15).Trim()
$Мобильный_телефон = $lines[18].Substring(18).Trim()
$Имя_пользователя_для_копирования_групп = $lines[20].Substring(29).Trim()

В данном фрагменте начинается цикл который проходит по каждому письму, преобразует в список строк и получает значения из него, в начале я добавил простую проверку на случай если на выделенный почтовый ящик попадет случайное письмо. Далее самое важное – создание учетки, и в моем случае контакта, на удаленном сервере, для этого используется команда Invoke-Command:

$Сессия = New-PSSession -ComputerName ###Сетевое имя или IP-адресс компа###
$Переменные = Invoke-Command -Session $Сессия -ScriptBlock {
param(####Все ваши переменные через запятую###)
команды на удаленном компе
return Переменные которые вернуться в массив обьектов "$Переменные"
} -ArgumentList ###Переменные через запятую которые вы передали в параметры###

Переменная “$Переменные” примет, после выполнения команды на удаленном компьютере, переменные, указанные в return – они понадобятся для отправления письма-отчета.

#Транслит имени
function global:Translit {} - Функция принимает кирилицу и возвращает латиницу
$count = 0
#---------------Получаем список пользователей AD-----------------
$adUsers = Get-ADUser -Filter * -Properties UserPrincipalName
#---------------------Создание логина---------------------------
#чтобы транслейтить имя надо написать: $Транслит = Translit($имя)
$Имя_пользователя = Translit($Имя[0] + "." + $Фамилия)
$Отображаемое_имя = "$Фамилия $Имя"
#---------------Проверка на однофамильцев-----------------
while ($adUsers.SamAccountName -like "*$Имя_пользователя*") { $count = $count + 1 $Имя_пользователя = Translit($Имя[0] + $count + "." + $Фамилия) $Отображаемое_имя = "$Фамилия $Имя $count"
#---------------Создание почты на основе логина-----------------
$Эл_почта = $Имя_пользователя + "@mail"

Теперь самое важное – создание учетной записи и контакта, Powershell не даст просто присвоить учетной записи пароль, для этого строку необходимо сначала преобразовать в защищенную.

#Пользователь
$Пароль = ConvertTo-SecureString -String "###Пароль###" -AsPlainText -Force
New-ADUser -SamAccountName "$Имя_пользователя" -UserPrincipalName "$Имя_пользователя" -Name $Отображаемое_имя -DisplayName $Отображаемое_имя -GivenName "$Имя" -Surname "$Фамилия" -Title "$Должность" -Mobile "$Мобильный_телефон" -OfficePhone "$Номер_телефона" -EmailAddress "$Эл_почта" -Department "$Отдел" -Company "$Организация" -AccountPassword $Пароль -Enabled $true -Path "OU=ТЕСТ,DC=domen,DC=local"
#Контакт
New-ADObject -Name "$Отображаемое_имя" -Type Contact -Path "OU=ТЕСТ_КОНТАКТЫ,OU=ТЕСТ,DC=domen,DC=local" -OtherAttributes @{DisplayName = $Отображаемое_имя; GivenName = "$Имя"; Sn = "$Фамилия"; Mobile = "$Мобильный_телефон"; Mail = "$Эл_почта";telephoneNumber = "444"; Title = "$Должность"; Department = "$Отдел"; Company = "$Организация"}
$Исходные_группы = Get-ADUser $Имя_пользователя_для_копирования_групп -Properties MemberOf | Select-Object -ExpandProperty MemberOf
foreach ($группы in $Исходные_группы) { Add-ADGroupMember -Identity $группы -Members $Имя_пользователя
}

На этом действия на сервере заканчиваются, закрываем скобки, и переходим в локальную сессию, в качестве отчета я отправлю письмо-ответ на адрес отправителя, для этого получаем переменные из объекта сессии и составляем письмо, после чего перемещаем письмо в папку “Исполнено”.

#Получение значений из сессии
$Имя_учетки = $Переменные.GetValue(0)
$Почта = $Переменные.GetValue(1)
#Ответное письмо
$Ответ = $Письмо.ReplyAll()
$Ответ.Body = @"
$Фамилия $Имя $Отчество
$Отдел
$Должность
$Организация
$Имя_учетки
$Почта
$Мобильный_телефон
$Номер_телефона
"@
$Ответ.Send( )
$Письмо.Move($Исполнено)

После завершения цикла, закрываем сессию с сервером и закрываем Outlook, через 10 секунд чтобы письма успели отправиться.

#Завершение сессии
Remove-PSSession -Session $Сессия
#Завершение Outlook
Start-Sleep -Seconds 10
Get-Process | Where-Object {$_.ProcessName -eq "OUTLOOK"} | Stop-Process

Образец моей заявки:

Заявка в IT - Новый сотрудник от 12.04.2024 10:34:49
Описание: Фамилия: Жданов
Имя: Дмитрий
Отчество: Юрьевич
Отдел: Служба Качества
Должность: Контролер пищевой продукции
Организация: АО "Агрофирма "Бунятино"
Подразделение: -
Номер телефона:
Мобильный телефон: -
Пользователь для копирования:

Полный листинг кода:

#----------------Создание сессии------------------------
$Сессия = New-PSSession -ComputerName ServerAD
#-------------------------Чтение почты-----------------------------
#Завершение Outlook
Get-Process | Where-Object {$_.ProcessName -eq "OUTLOOK"} | Stop-Process
Start-Sleep -Seconds 10
# Создание объекта Outlook
$outlook = New-Object -ComObject Outlook.Application
# Получение коллекции папок
$folders = $outlook.Session.Folders.Item("auto-user@agro-holding.ru").Folders
# Выбор папки "Входящие"
$Входящие = $folders.Item("Входящие")
$Исполнено = $folders.Item("Исполнено")
# Получение последнего письма
$Письма = $Входящие.Items | Sort-Object ReceivedTime -Descending
#-------------------------Рабочий алгоритм-----------------------------
#Получение значений переменных из письма
foreach ($Письмо in $Письма) {
$lines = $Письмо.Body -split "`n"
#Условие чтения письма
if ($lines[0].Substring(0, 29) -ne "Заявка в IT - Новый сотрудник") {continue}
$Дата_заявки = $lines[0].Substring(32).Trim()
$Фамилия = $lines[2].Substring(18).Trim()
$Имя = $lines[4].Substring(4).Trim()
$Отчество = $lines[6].Substring(9).Trim()
$Отдел = $lines[8].Substring(6).Trim()
$Должность = $lines[10].Substring(10).Trim()
$Организация = $lines[12].Substring(12).Trim()
$Подразделение = $lines[14].Substring(14).Trim()
$Номер_телефона = $lines[16].Substring(15).Trim()
$Мобильный_телефон = $lines[18].Substring(18).Trim()
$Имя_пользователя_для_копирования_групп = $lines[20].Substring(29).Trim()
#---------------Основная команда создания пользователя на удаленном сервере-----------------
$Переменные = Invoke-Command -Session $Сессия -ScriptBlock { param($Фамилия, $Имя, $Отчество, $Отдел, $Должность, $Организация, $Подразделение, $Номер_телефона, $Мобильный_телефон, $Имя_пользователя_для_копирования_групп)
#---------------Функция транслита-----------------
#Транслит имени
function global:Translit {
param([string]$inString)
$Translit = @{
[char]'а' = "a"
[char]'А' = "a"
[char]'б' = "b"
[char]'Б' = "b"
[char]'в' = "v"
[char]'В' = "v"
[char]'г' = "g"
[char]'Г' = "g"
[char]'д' = "d"
[char]'Д' = "d"
[char]'е' = "e"
[char]'Е' = "e"
[char]'ё' = "yo"
[char]'Ё' = "yo"
[char]'ж' = "zh"
[char]'Ж' = "zh"
[char]'з' = "z"
[char]'З' = "z"
[char]'и' = "i"
[char]'И' = "i"
[char]'й' = "j"
[char]'Й' = "j"
[char]'к' = "k"
[char]'К' = "k"
[char]'л' = "l"
[char]'Л' = "l"
[char]'м' = "m"
[char]'М' = "m"
[char]'н' = "n"
[char]'Н' = "n"
[char]'о' = "o"
[char]'О' = "o"
[char]'п' = "p"
[char]'П' = "p"
[char]'р' = "r"
[char]'Р' = "r"
[char]'с' = "s"
[char]'С' = "s"
[char]'т' = "t"
[char]'Т' = "t"
[char]'у' = "u"
[char]'У' = "u"
[char]'ф' = "f"
[char]'Ф' = "f"
[char]'х' = "h"
[char]'Х' = "h"
[char]'ц' = "c"
[char]'Ц' = "c"
[char]'ч' = "ch"
[char]'Ч' = "ch"
[char]'ш' = "sh"
[char]'Ш' = "sh"
[char]'щ' = "sch"
[char]'Щ' = "sch"
[char]'ъ' = ""
[char]'Ъ' = ""
[char]'ы' = "y"
[char]'Ы' = "y"
[char]'ь' = ""
[char]'Ь' = ""
[char]'э' = "e"
[char]'Э' = "e"
[char]'ю' = "yu"
[char]'Ю' = "yu"
[char]'я' = "ya"
[char]'Я' = "ya"
}
$outCHR=""
foreach ($CHR in $inCHR = $inString.ToCharArray())
{
if ($Translit[$CHR] -cne $Null )
{$outCHR += $Translit[$CHR]}
else
{$outCHR += $CHR}
}
Write-Output $outCHR
}
$count = 0
#---------------Получаем список пользователей AD-----------------
$adUsers = Get-ADUser -Filter * -Properties UserPrincipalName
#---------------------Получение логина---------------------------
#чтобы транслейтить имя надо написать: $Транслит = Translit($имя)
$Имя_пользователя = Translit($Имя[0] + "." + $Фамилия)
$Отображаемое_имя = "$Фамилия $Имя"
#---------------Проверка на однофамильцев-----------------
while ($adUsers.SamAccountName -like "*$Имя_пользователя*") { $count = $count + 1 $Имя_пользователя = Translit($Имя[0] + $count + "." + $Фамилия) $Отображаемое_имя = "$Фамилия $Имя $count"
}
#---------------Создание почты на основе логина-----------------
$Эл_почта = $Имя_пользователя + "@почта"
#---------------------Добавиление в AD-----------------------------
#Пользователь
$Пароль = ConvertTo-SecureString -String "пароль" -AsPlainText -Force
New-ADUser -SamAccountName "$Имя_пользователя" -UserPrincipalName "$Имя_пользователя" -Name $Отображаемое_имя -DisplayName $Отображаемое_имя -GivenName "$Имя" -Surname "$Фамилия" -Title "$Должность" -Mobile "$Мобильный_телефон" -OfficePhone "$Номер_телефона" -EmailAddress "$Эл_почта" -Department "$Отдел" -Company "$Организация" -AccountPassword $Пароль -Enabled $true -Path "OU=ТЕСТ,DC=bun,DC=local"
#Контакт
New-ADObject -Name "$Отображаемое_имя" -Type Contact -Path "OU=ТЕСТ_КОНТАКТЫ,OU=ТЕСТ,DC=bun,DC=local" -OtherAttributes @{DisplayName = $Отображаемое_имя; GivenName = "$Имя"; Sn = "$Фамилия"; Mobile = "$Мобильный_телефон"; Mail = "$Эл_почта";telephoneNumber = "444"; Title = "$Должность"; Department = "$Отдел"; Company = "$Организация"}
#-----------Копируем группы пользователя из контейнера-------------
$Исходные_группы = Get-ADUser $Имя_пользователя_для_копирования_групп -Properties MemberOf | Select-Object -ExpandProperty MemberOf
foreach ($группы in $Исходные_группы) { Add-ADGroupMember -Identity $группы -Members $Имя_пользователя
}
#-----------Возвращение переменных из сессии для ответного письма-------------
return $Имя_пользователя, $Эл_почта, $Фамилия, $Имя, $Отчество, $Отдел, $Должность, $Организация, $Подразделение, $Номер_телефона, $Мобильный_телефон, $Имя_пользователя_для_копирования_групп
} -ArgumentList $Фамилия, $Имя, $Отчество, $Отдел, $Должность, $Организация, $Подразделение, $Номер_телефона, $Мобильный_телефон, $Имя_пользователя_для_копирования_групп
#Получение значений из сессии
$Имя_учетки = $Переменные.GetValue(0)
$Почта = $Переменные.GetValue(1)
#Ответное письмо
$Ответ = $Письмо.ReplyAll()
$Ответ.Body = @"
$Фамилия $Имя $Отчество
$Отдел
$Должность
$Организация
$Имя_учетки
$Почта
$Мобильный_телефон
$Номер_телефона
"@
$Ответ.Send( )
$Письмо.Move($Исполнено)
}
#Завершение Outlook
Start-Sleep -Seconds 10
Get-Process | Where-Object {$_.ProcessName -eq "OUTLOOK"} | Stop-Process
#Завершение сессии
Remove-PSSession -Session $Сессия

Надеюсь вам помогла моя статья, я постарался максимально понятно разделить код на составные части чтобы его части можно было поменять на собственные.