I am unable to get all the INSTALLED voices for a multi-lingual Text-to-Speech solution, although all installed languages are showing up. I know similar questions have been asked before but there don't seem to be any answers even yet except for some registry tweaks. The code is as under:
foreach (InputLanguage lang in InputLanguage.InstalledInputLanguages)
{
txtText.AppendText(Environment.NewLine + Environment.NewLine + lang.Culture.EnglishName);
using (SpeechSynthesizer synthesizer = new SpeechSynthesizer())
{
var voiceCollection = synthesizer.GetInstalledVoices(new CultureInfo(lang.Culture.Name));
foreach (InstalledVoice voice in voiceCollection)
{
VoiceInfo info = voice.VoiceInfo;
txtText.AppendText(Environment.NewLine + "Name: " + info.Name);
txtText.AppendText(Environment.NewLine + "Gender: " + info.Gender);
txtText.AppendText(Environment.NewLine + "Culture: " + info.Culture + Environment.NewLine);
}
}
}
I have found the solution. As you said, we have to modify the registry to get all the
voices successfully.
However, we don't need to modify it manually. You can run the following powershell code in
windows powershell.(Don't forget run as administrator for powershell)
$sourcePath = 'HKLM:\software\Microsoft\Speech_OneCore\Voices\Tokens' #Where the OneCore voices live
$destinationPath = 'HKLM:\SOFTWARE\Microsoft\Speech\Voices\Tokens' #For 64-bit apps
$destinationPath2 = 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\SPEECH\Voices\Tokens' #For 32-bit apps
cd $destinationPath
$listVoices = Get-ChildItem $sourcePath
foreach($voice in $listVoices)
{
$source = $voice.PSPath #Get the path of this voices key
copy -Path $source -Destination $destinationPath -Recurse
copy -Path $source -Destination $destinationPath2 -Recurse
}
After running this, you can run your current winform app again. You can see all the
installed voices.
Here is my tested result:
Related
I'm writing a form that will upload any file in a folder to a Microsoft Teams share. My code already manage to upload the files, but keep showing me the log in form of microsoft 365 for each file, instead asking only the first time.
this is the code:
private void Upload()
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
PowerShell psinstance = PowerShell.Create();
//fill some vars and connect (once, hopefully)
psinstance.AddScript("$SharepointURL = '" + LINK-TO-THE-DESIRED-TEAM + "'");
psinstance.AddScript("$OutPath = '" + SOURCE-DIRECTORY + "'");
psinstance.AddScript("Connect-PnPOnline -SPOManagementShell -url $SharepointURL -cleartokencache");
//upload each file in the directory
psinstance.AddScript("$Files = Get-ChildItem -path $OutPath");
psinstance.AddScript("foreach ($File in $Files){ Add-PnPFile -Folder '" + DESIRED-CHANNEL-DIRECTORY + "' -Path $File.FullName }");
//execute the script
Collection <PSObject> results = psinstance.Invoke();
//get possible errors
Collection<ErrorRecord> Errors = psinstance.Streams.Error.ReadAll();
runspace.Close();
}
The same powershell code, if executed in the powershell console, works like a sharm. This is driving me crazy, can you help me?
I need help to solve problem to auto-mate deploy .Net Core web app Api to a server.
As you know is impossible to overwrite .dll if you not stop AppPool before , and there is no solution for that in IIS .
Actually by using PowerShell I can perform a script to do what I need the script is showed below:
PowerShell script
Actually I need a console application to performe same work , I found that I can use Microsoft.PowerShell.SDK to implement a solution.
public static void RunC()
{
string us = "xxxxxxxxxxxxx"; //User
string pw = "xxxxxxxxxxxxxxxx";//Passwprd
string sv = "xxx.x.xx.xxx";//Server
string apppoolname = "xxxxxxxxxxxxx";
StringBuilder script = new StringBuilder();
//Creazione script PS
script.Append("$password = ConvertTo-SecureString \"" + pw + "\" -AsPlainText -Force" + Environment.NewLine);
script.Append("$user = \"" + us + "\"" + Environment.NewLine);
script.Append("$cred = New-Object System.Management.Automation.PSCredential ($user,$password)" + Environment.NewLine);
script.Append("Enter-PSSession -ComputerName \"" + sv + "\" -Credential $cred" + Environment.NewLine);
script.Append("Import-Module webadministration");
script.Append("Stop-WebAppPool \"" + apppoolname + "\"");
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(script.ToString());
//pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
StringBuilder sb = new StringBuilder();
foreach (PSObject pSObject in results)
{
sb.AppendLine(pSObject.ToString());
}
Console.WriteLine(sb.ToString());
}
But I got error show in the image , seams Module is not lodaded or something similar ..
some one can help me in some way?
Thank you :-)
I dont see the error in the image, but if it is a issue caused by the WebAdministration not being imported this should fix it:
#Requires -Modules WebAdministration
Place that at the begging of the script and it will try to import the module if it's not available already in the session. Microsoft documentation:
Specifies PowerShell modules that the script requires. Enter the module name and an optional version number.
If the required modules aren't in the current session, PowerShell imports them. If the modules can't be imported, PowerShell throws a terminating error.
source
Hope it helps, good luck.
I have an application, that allows the user to configure basic WMI settings on a Win 10 IoT machine.
I am currently struggling with reading all WEKF_PredefinedKey settings, that are enabled.
I am simply running a skript, that I added as string to the project settings named ReadEnabledKeys:
$CommonParams = #{"namespace"="root\standardcimv2\embedded"}
$CommonParams += $PSBoundParameters
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned;
$keys = Get-WMIObject -class WEKF_PredefinedKey #CommonParams
foreach($k in $keys)
{
if($k.Enabled -eq $false)
{
"$k";
}
}
My call in C# code looks like this (Note: using System.Management.Automation):
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript(Properties.Settings.Default.ReadEnabledKeys);
var result = PowerShellInstance.Invoke();
}
My variable result will always stay empty.
If I run the skript in Powershell directly, the output is just fine (all shortcuts, that are currently not disabled).
I have something similar programmed with the unified write filter, where I enable and disable it:
$COMPUTER = "localhost"
$NAMESPACE = "root\standardcimv2\embedded"
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned;
$objUWFInstance = Get-WMIObject -namespace $NAMESPACE -class UWF_Filter;
$retval = $objUWFInstance.Enable();
if ($retval.ReturnValue -eq 0) {"Unified Write Filter will be enabled after the next system restart."}
else {"Unknown Error: " + "{0:x0}" -f $retval.ReturnValue}
And the C# call:
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript(Properties.Settings.Default.EnableUWF);
// [0] = result or error
var result = PowerShellInstance.Invoke();
if (result[0].ToString().ToLower().Contains("enabled"))
MessageBox.Show(result[0].ToString(), "", MessageBoxButton.OK, MessageBoxImage.Information);
else
MessageBox.Show("Error when enabling the filter! " + Environment.NewLine + result[0].ToString(), "",
MessageBoxButton.OK, MessageBoxImage.Error);
}
Here my result variable will be filled with the expected strings.
I have tried Write-Host $k, as I suspected something wrong with the stream, but this was without any success.
The output in Powershell looks like this:
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\Newfolder\Untitled1.ps1
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Alt"\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Application"
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Ctrl+Esc"
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Ctrl+F4"
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Ctrl+Tab"
.
.
.
Can anyone tell me, what the problem is?
The problem appears to be with your script. Setting the ExecutionPolicy midstream doesn't do anything and you aren't writing a function so adding $PSBoundParameters also doesn't do anything. Here's an example that should work (I'd specify PS version in the future. I know you're on v5.1/win10 due to keyboard filtering)
$collection = [System.Collections.Generic.List[string]]::new()
foreach ($key in (Get-CimInstance -Namespace 'root\standardcimv2\embedded' -ClassName WEKF_PredefinedKey)) {
if (-not $key.Enabled) {
$collection.Add($key.ToString())
}
}
return $collection
(simplified)
#(Get-CimInstance -Namespace root\standardcimv2\embedded -ClassName WEKF_PredefinedKey).
Where{-not $_.Enabled}.
ForEach('ToString')
Example:
using (PowerShell ps = PowerShell.Create())
{
string script = #"Import-Module -Name C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1 -ErrorAction Stop; #(Get-WmiObject -Namespace root\standardcimv2\embedded -Class WEKF_PredefinedKey -ErrorAction Stop).Where{-not $_.Enabled}.ForEach('ToString')";
ps.AddScript(script);
var result = ps.Invoke();
}
I want to extract a zip file in Downloads folder to Desktop using PowerShell and C#.
I need it to work with Windows 7, 8, & 10.
I'm trying to take these PowerShell commands
extract https://stackoverflow.com/a/36472063/6806643
overwrite https://stackoverflow.com/a/5711383/6806643
chain https://superuser.com/a/612413/740888
$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace("zip file path")
foreach ($item in $zip.items()) {
$shell.Namespace("unzip destination path").CopyHere($item)
}
And run it through a C# Process.Start()
Process.Start("powershell.exe",
"timeout 3; "
+ "$shell = New-Object -ComObject shell.application; "
+ "$zip = $shell.NameSpace(\"C:\\Users\\Matt\\Downloads\\MyFile.zip\"); "
+ "foreach ($item in $zip.items()) {$shell.Namespace(\"C:\\Users\\Matt\\Desktop\\\").CopyHere($item, 0x14)}"
);
Problem
PowerShell launches but fails to extract, and closes out before I can read the error.
However, if I copy paste those chained commands into PowerShell without C#, it works.
$shell = New-Object -ComObject shell.application; $zip = $shell.NameSpace('C:\Users\Matt\Downloads\MyFile.zip'); foreach ($item in $zip.items()) {$shell.Namespace('C:\Users\Matt\Desktop\').CopyHere($item, 0x14)}
This works but it's for PowerShell 5 only.
Process.Start("powershell.exe",
"timeout 3; Expand-Archive 'C:\\Users\\Matt\\Downloads\\MyFile.zip' -Force -DestinationPath 'C:\\Users\\Matt\\Desktop\\'"
);
I may have solved it while writing out the question and refactoring other chained commands.
I found this article and combined it with the other code.
https://www.howtogeek.com/tips/how-to-extract-zip-files-using-powershell/
Process.Start("powershell.exe",
"-nologo -noprofile -command "
+ "timeout 3; "
+ "$shell = new-object -com shell.application; "
+ "$zip = $shell.NameSpace('C:\\Users\\Matt\\Downloads\\MyFile.zip'); "
+ "foreach ($item in $zip.items()) {$shell.Namespace('C:\\Users\\Matt\\Desktop\\').CopyHere($item, 0x14)}"
);
The differences are:
adding -nologo -noprofile -command
-com instead of -ComObject
single quotes ' instead of double " around paths.
And chaining messages with Write-Host \"hello\" -NoNewLine instead of echo.
I have been working on an auto-installer as I have to reinstall Windows a lot, one of the software I install is Visual Studio 2013 which comes as an ISO.
I have written some code that mounts the ISO, but I can't work out how to return the drive letter for when I run the setup.
else if (soft == "Visual Studio 2013 Pro")
{
var isoPath = Loc.path + Loc.vs2013pro;
using (var ps = PowerShell.Create())
{
ps.AddCommand("Mount-DiskImage").AddParameter("ImagePath", isoPath).Invoke();
}
var proc = System.Diagnostics.Process.Start(Loc.path + Loc.vs2013pro);
proc.WaitForExit();
System.IO.File.Copy(Loc.path + #"\Visual Studio 2013 Pro\Serial.txt", folder + "/Serials/VS2013Pro Serial.txt");
}
Add the PassThru parameter, this causes a MSFT_DiskImage to be returned. The DevicePath property has the mount point in it.
The marked answer doesn't work for me so based on a blog post I found on PowerShell ISO mounting & unmounting I decided to code this up as a good example using C# (required references System.Management.Automation &
System.Management.Automation.Runspaces).
string isoPath = "C:\\Path\\To\\Image.iso";
using (var ps = PowerShell.Create())
{
//Mount ISO Image
var command = ps.AddCommand("Mount-DiskImage");
command.AddParameter("ImagePath", isoPath);
command.Invoke();
ps.Commands.Clear();
//Get Drive Letter ISO Image Was Mounted To
var runSpace = ps.Runspace;
var pipeLine = runSpace.CreatePipeline();
var getImageCommand = new Command("Get-DiskImage");
getImageCommand.Parameters.Add("ImagePath", isoPath);
pipeLine.Commands.Add(getImageCommand);
pipeLine.Commands.Add("Get-Volume");
string driveLetter = null;
foreach (PSObject psObject in pipeLine.Invoke())
{
driveLetter = psObject.Members["DriveLetter"].Value.ToString();
Console.WriteLine("Mounted On Drive: " + driveLetter);
}
pipeLine.Commands.Clear();
//Unmount Via Image File Path
command = ps.AddCommand("Dismount-DiskImage");
command.AddParameter("ImagePath", isoPath);
ps.Invoke();
ps.Commands.Clear();
//Alternate Unmount Via Drive Letter
ps.AddScript("$ShellApplication = New-Object -ComObject Shell.Application;" +
"$ShellApplication.Namespace(17).ParseName(\"" + driveLetter + ":\").InvokeVerb(\"Eject\")");
ps.Invoke();
ps.Commands.Clear();
}