英文:
System.Windows.Forms.ComboBoxStyle Unable to find type | Powershell
问题
I'm currently creating a tool for my IT department in PowerShell.
I'm new to programming so I google and ask AI sometimes (I already asked AI and googled about this issue but neither could help).
My problem is about System.Windows.Forms.ComboBoxStyle being marked red even though the System.Windows.Forms is imported at the top. But all normal GUI components (which also need System.Windows.Forms) work. When I try to run it I also get an error saying
ParserError: Just some file path\LeihgeraeteManager\LeihgeraeteManager.ps1:175:45
Line |
175 | … eDropdown.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropD …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Unable to find type [System.Windows.Forms.ComboBoxStyle].
The weird thing is that when I run the line
Add-Type -AssemblyName System.Windows.Forms
at the top of the script manually (select and F8 in Visual Studio Code), it works after that. When I restart Visual Studio Code it won't work again until I do that.
I already tried it in the normal PowerShell ISE Editor but I get the same results there.
I use PowerShell Version 7.3.6 btw.
Here is the full code I've written so far if it helps (It's not finished yet + I've censored some file paths and Names due to data protection of internal stuff):
#############################################################
$FilePath = "Example" #Change this if the CSV Path changed
$ScriptVersion = 0.1.0.0 #Change this if it's a new version
#############################################################
Add-Type -AssemblyName System.Windows.Forms
function Write-Log($Message, $Path = $PSScriptRoot + "\", $Debug = $true, $reset = $false) {
if ($reset -eq $True) {
if (Test-Path -Path ($Path + "log.txt")) { # Check if File already exists
Remove-Item -Path ($Path + "log.txt")
return #Exit function
}
}
if ($Debug) {Write-Debug $Message} # Write Debug
$Path = $Path + "log.txt" # Add Filename to Text
if (Test-Path -Path $Path) { # Check if File already exists
} else {
New-Item -Path $Path -ItemType File -Force | Out-Null #Creating new File
Add-Content -Path $Path -Value "[dd-MM HH:mm:ss]" #Adding first line
}
$CurrentDate = Get-Date -Format "dd-MM HH:mm:ss" #Getting date
$LogMessage = "[$CurrentDate] $Message" #Adding Date and message together
Add-Content -Path $Path -Value $LogMessage #Adding the Message to the log file
}
function PopUpWindow ($WindowTitle, $WindowText, $WindowWidth = 250, $WindowHeight = 200) {
<#
.SYNOPSIS
Simple function for creating
#>
$PopUp = New-Object System.Windows.Forms.Form
$PopUp.Width = $WindowWidth
$PopUp.Height = $WindowHeight
$PopUp.Text = "$WindowTitle"
$PopUp.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle #Locking window size
$PopUp.MaximizeBox = $false #Disabling Maximize Button
$PopUp.MinimizeBox = $false #Disabling Minimize Button
$PopUpText = New-Object System.Windows.Forms.Label
$PopUpText.Location = New-Object System.Drawing.Point(10,10)
$PopUpText.AutoSize = $true
$PopUpText.Text = "$($WindowText)"
$PopUp.Controls.Add($PopUpText)
$ButtonLocationWidth = (($WindowWidth - 65) / 2)
$ButtonLocationHeight = ($WindowHeight - 70)
$PopupCancelButton = new-object System.Windows.Forms.Button # Creating the "Start" button
$PopupCancelButton.Location = New-Object System.Drawing.Point($ButtonLocationWidth, $ButtonLocationHeight)
$PopupCancelButton.Size = New-Object System.Drawing.Size(60, 25)
$PopupCancelButton.Text = 'Close'
$PopupCancelButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$PopUp.AcceptButton = $PopupCancelButton
$PopUp.Controls.Add($PopupCancelButton)
[void]$PopUp.ShowDialog()
}
function Get-FileAvailable($Path){
if (Test-Path -Path $Path) { # If file exists...
$IsAvail = $true # ... set variable to true
} else {$IsAvail = $false} # If not then set to false
return $IsAvail # Return the result
}
Write-Log -reset $true # Deleting old Log file if there is one
Write-Log "Started script and set functions" #Log
class Manager{ # Manager is saving all of the device objects and has all important Functions
hidden [array]$Devices #Device Array
AddDevice() { # This function simply creates a new device with the given data
Write-Log "Starting AddWindow GUI creation..."
$AddWindow = New-Object System.Windows.Forms.Form
$AddWindow.Width = 1000
$AddWindow.Height = 1000
$AddWindow.Text = "Enter Information"
Write-Log "Defined Window"
#Computer Name
$AddWindowTextCN = New-Object System.Windows.Forms.Label
$AddWindowTextCN.Location = New-Object System.Drawing.Point(50,30)
$AddWindowTextCN.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextCN.Text = "Enter Device Name:"
$AddWindowBoxCN = New-Object System.Windows.Forms.TextBox
$AddWindowBoxCN.Location = New-Object System.Drawing.Point(50,50)
$AddWindowBoxCN.Size = New-Object System.Drawing.Size(260,20)
$AddWindowBoxCN.Text = "NBW03"
$AddWindow.Controls.Add($AddWindowTextCN)
$AddWindow.Controls.Add($AddWindowBoxCN)
#Model
$AddWindowTextM = New-Object System.Windows.Forms.Label
$AddWindowTextM.Location = New-Object System.Drawing.Point(50,80)
$AddWindowTextM.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextM.Text = "Enter Device Model:"
$AddWindowBoxM = New-Object System.Windows.Forms.TextBox
$AddWindowBoxM.Location = New-Object System.Drawing.Point(50,100)
$AddWindowBoxM.Size = New-Object System.Drawing.Size(260,20)
$AddWindowBoxM.Text = ""
$AddWindow.Controls.Add($AddWindowTextM)
$AddWindow.Controls.Add($AddWindowBoxM)
#Serial Number
$AddWindowTextSN = New-Object System.Windows.Forms.Label
$AddWindowTextSN.Location = New-Object System.Drawing.Point(50,130)
$AddWindowTextSN.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextSN.Text = "Enter Serial Number:"
$AddWindow
<details>
<summary>英文:</summary>
I'm currently creating a tool for my IT department in PowerShell.
I'm new to programming so I google and ask AI sometimes (I already asked AI and googled about this issue but neither could help).
My problem is about System.Windows.Forms.ComboBoxStyle being marked red even though the System.Windows.Forms is imported at the top. But all normal GUI components (which also need System.Windows.Forms) work. When I try to run it I also get an error saying
ParserError: Just some file path\LeihgeraeteManager\LeihgeraeteManager.ps1:175:45
Line |
175 | … eDropdown.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropD …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Unable to find type [System.Windows.Forms.ComboBoxStyle].
The weird thing is that when I run the line
Add-Type -AssemblyName System.Windows.Forms
at the top of the script manually (select and F8 in Visual Studio Code), it works after that.
When I restart Visual Studio Code it won't work again until I do that.
I already tried it in the normal PowerShell ISE Editor but I get the same results there.
I use PowerShell Version 7.3.6 btw.
Here is the full code I've written so far if it helps (It's not finished yet + I've censored some file paths and Names due to data protection of internal stuff):
#############################################################
$FilePath = "Example" #Change this if the CSV Path changed
$ScriptVersion = 0.1.0.0 #Change this if it's a new version
#############################################################
Add-Type -AssemblyName System.Windows.Forms
function Write-Log($Message, $Path = $PSScriptRoot + "", $Debug = $true, $reset = $false) {
if ($reset -eq $True) {
if (Test-Path -Path ($Path + "log.txt")) { # Check if File already exists
Remove-Item -Path ($Path + "log.txt")
return #Exit function
}
}
if ($Debug) {Write-Debug $Message} # Write Debug
$Path = $Path + "log.txt" # Add Filename to Text
if (Test-Path -Path $Path) { # Check if File already exists
} else {
New-Item -Path $Path -ItemType File -Force | Out-Null #Creating new File
Add-Content -Path $Path -Value "[dd-MM HH:mm:ss]" #Adding first line
}
$CurrentDate = Get-Date -Format "dd-MM HH:mm:ss" #Getting date
$LogMessage = "[$CurrentDate] $Message" #Adding Date and message together
Add-Content -Path $Path -Value $LogMessage #Adding the Message to the log file
}
function PopUpWindow ($WindowTitle, $WindowText, $WindowWidth = 250, $WindowHeight = 200) {
<#
.SYNOPSIS
Simple function for creating
#>
$PopUp = New-Object System.Windows.Forms.Form
$PopUp.Width = $WindowWidth
$PopUp.Height = $WindowHeight
$PopUp.Text = "$WindowTitle"
$PopUp.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle #Locking window size
$PopUp.MaximizeBox = $false #Disabling Maximize Button
$PopUp.MinimizeBox = $false #Disabling Minimize Button
$PopUpText = New-Object System.Windows.Forms.Label
$PopUpText.Location = New-Object System.Drawing.Point(10,10)
$PopUpText.AutoSize = $true
$PopUpText.Text = "$($WindowText)"
$PopUp.Controls.Add($PopUpText)
$ButtonLocationWidth = (($WindowWidth - 65) / 2)
$ButtonLocationHeight = ($WindowHeight - 70)
$PopupCancelButton = new-object System.Windows.Forms.Button # Creating the "Start" button
$PopupCancelButton.Location = New-Object System.Drawing.Point($ButtonLocationWidth, $ButtonLocationHeight)
$PopupCancelButton.Size = New-Object System.Drawing.Size(60, 25)
$PopupCancelButton.Text = 'Close'
$PopupCancelButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$PopUp.AcceptButton = $PopupCancelButton
$PopUp.Controls.Add($PopupCancelButton)
[void]$PopUp.ShowDialog()
}
function Get-FileAvailable($Path){
if (Test-Path -Path $Path) { # If file exists...
$IsAvail = $true # ... set variable to true
} else {$IsAvail = $false} # If not then set to false
return $IsAvail # Return the result
}
Write-Log -reset $true # Deleting old Log file if there is one
Write-Log "Started script and set functions" #Log
class Manager{ # Manager is saving all of the device objects and has all important Fuctions
hidden [array]$Devices #Device Array
AddDevice() { # This function simply creates a new device with the given data
Write-Log "Starting AddWindow GUI creation..."
$AddWindow = New-Object System.Windows.Forms.Form
$AddWindow.Width = 1000
$AddWindow.Height = 1000
$AddWindow.Text = "Enter Information"
Write-Log "Defined Window"
#Computer Name
$AddWindowTextCN = New-Object System.Windows.Forms.Label
$AddWindowTextCN.Location = New-Object System.Drawing.Point(50,30)
$AddWindowTextCN.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextCN.Text = "Enter Device Name:"
$AddWindowBoxCN = New-Object System.Windows.Forms.TextBox
$AddWindowBoxCN.Location = New-Object System.Drawing.Point(50,50)
$AddWindowBoxCN.Size = New-Object System.Drawing.Size(260,20)
$AddWindowBoxCN.Text = "NBW03"
$AddWindow.Controls.Add($AddWindowTextCN)
$AddWindow.Controls.Add($AddWindowBoxCN)
#Model
$AddWindowTextM = New-Object System.Windows.Forms.Label
$AddWindowTextM.Location = New-Object System.Drawing.Point(50,80)
$AddWindowTextM.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextM.Text = "Enter Device Model:"
$AddWindowBoxM = New-Object System.Windows.Forms.TextBox
$AddWindowBoxM.Location = New-Object System.Drawing.Point(50,100)
$AddWindowBoxM.Size = New-Object System.Drawing.Size(260,20)
$AddWindowBoxM.Text = ""
$AddWindow.Controls.Add($AddWindowTextM)
$AddWindow.Controls.Add($AddWindowBoxM)
#Serial Number
$AddWindowTextSN = New-Object System.Windows.Forms.Label
$AddWindowTextSN.Location = New-Object System.Drawing.Point(50,130)
$AddWindowTextSN.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextSN.Text = "Enter Serial Number:"
$AddWindowBoxSN = New-Object System.Windows.Forms.TextBox
$AddWindowBoxSN.Location = New-Object System.Drawing.Point(50,150)
$AddWindowBoxSN.Size = New-Object System.Drawing.Size(260,20)
$AddWindowBoxSN.Text = ""
$AddWindow.Controls.Add($AddWindowTextSN)
$AddWindow.Controls.Add($AddWindowBoxSN)
#Owner
$AddWindowTextO = New-Object System.Windows.Forms.Label
$AddWindowTextO.Location = New-Object System.Drawing.Point(50,130)
$AddWindowTextO.Size = New-Object System.Drawing.Size(200,15)
$AddWindowTextO.Text = "Enter Manager of Device:"
$AddWindowBoxO = New-Object System.Windows.Forms.TextBox
$AddWindowBoxO.Location = New-Object System.Drawing.Point(50,50)
$AddWindowBoxO.Size = New-Object System.Drawing.Size(260,20)
$AddWindowBoxO.Text = ""
$AddWindow.Controls.Add($AddWindowTextO)
$AddWindow.Controls.Add($AddWindowBoxO)
$AddWindow.ShowDialog()
#$newDevice = [Leihgeraete]::new($ComputerName, $Model, $SerialNumber, $Owner, $InstallHinweis)
Write-Log "Adding new Device" #Log
#$this.Devices += $newDevice # Adds the new device to array
Write-Log "Added new device to device array" #Log
}
RemoveDevice(){
Write-Log "Starting RemoveWindow GUI creation..." #Log
$RemoveWindow = New-Object System.Windows.Forms.Form #Window to choose the device
$RemoveWindow.Width = 475
$RemoveWindow.Height = 200
$RemoveWindow.Text = "Choose Device"
Write-Log "Defined Window" #Log
$ChooseRemDevText = New-Object System.Windows.Forms.Label # New Text for the Window
$ChooseRemDevText.Location = New-Object System.Drawing.Point(50,30)
$ChooseRemDevText.Size = New-Object System.Drawing.Size(400,15)
$ChooseRemDevText.Text = "Choose Computer to delete:"
Write-Log "Added Text" #Log
$RemoveWindow.Controls.Add($ChooseRemDevText) # Adding Text to the window
$RemDeviceDropdown = New-Object System.Windows.Forms.ComboBox # Creating the dropdown menu to choose device
$RemDeviceDropdown.Location = New-Object System.Drawing.Point(50,50)
$RemDeviceDropdown.Width = 340
$RemDeviceDropdown.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList # Setting Style so User can't enter custom things
$RemDeviceDropdown.Items.Add("<None>") # Adding Default Choice
foreach ($device in $this.Devices) { # Adding all Names to menu that are in devices array
$RemDeviceDropdown.Items.Add($device.ComputerName)
}
$RemDeviceDropdown.SelectedIndex = 0 # Setting <None> to default
$RemoveWindow.Controls.Add($RemDeviceDropdown)
Write-Log "Added and filled Dropdown Menu" #Log
Write-Log "Creating Buttons..." #Log
$DeleteButton = new-object System.Windows.Forms.Button # Creating the "Delete" button
$DeleteButton.Location = '90, 100'
$DeleteButton.Size = '100, 40'
$DeleteButton.Text = 'Delete'
$DeleteButton.Add_Click({ #Runs when button is clicked
Write-Log "Delete button pressed" #Log
[string]$selectedDeviceDel = $RemDeviceDropdown.SelectedItem # Saving selected device
if ($selectedDeviceDel -ne "<None>") {
Write-Log "Selected device is not <None>" #Log
$RemoveWindowConf = New-Object System.Windows.Forms.Form #Window to confirm the deletion
$RemoveWindowConf.Width = 350
$RemoveWindowConf.Height = 200
$RemoveWindowConf.Text = "Confirm"
Write-Log "Created new confirmation Window" #Log
$ConfText = New-Object System.Windows.Forms.Label # Confirm Text
$ConfText.Location = New-Object System.Drawing.Point(50, 30)
$ConfText.Size = New-Object System.Drawing.Size(160, 15)
$ConfText.Text = "Do you really want to delete "
Write-Log "Added Text" #Log
$SelectedDeviceDelText = New-Object System.Windows.Forms.Label # Adding Computer Name in Bold for better reading
$SelectedDeviceDelText.Location = New-Object System.Drawing.Point(210, 30)
$SelectedDeviceDelText.Size = New-Object System.Drawing.Size(50, 15)
$SelectedDeviceDelText.Text = $selectedDeviceDel
$SelectedDeviceDelText.Font = [System.Drawing.Font]::new($SelectedDeviceDelText.Font, [System.Drawing.FontStyle]::Bold)
Write-Log "Added Device Name" #Log
$RemoveWindowConf.Controls.Add($ConfText)
$RemoveWindowConf.Controls.Add($SelectedDeviceDelText)
$ConfButtonY = new-object System.Windows.Forms.Button # Creating the "YES" button
$ConfButtonY.Location = '50, 80'
$ConfButtonY.Size = '100, 40'
$ConfButtonY.Text = 'YES'
Write-Log "Creating Buttons" #Log
$ConfButtonY.Add_Click({ # When click Yes the run the deletion process
Write-Log "Clicked on Yes on confirm Window" #Log
$updatedDevices = @()
$deviceRemoved = $false
foreach ($device in $Manager.Devices) { #Check if chosen device is in the array and deletes it after that
[string]$StrDev = $device.ComputerName # Converting Name to string
if ($StrDev -ne $selectedDeviceDel) {
$updatedDevices += $device
Write-Log "Added $device to new temporary array" #Log
} else {
$deviceRemoved = $true
Write-Log "Not added $device to new temporary array because it has the same value as the selected Device" #Log
}
}
if ($deviceRemoved) {
$Manager.Devices = $updatedDevices # Writing updated array in the original one
Write-Log "Replaced array in Manager class" #Log
}
$RemoveWindowConf.Close() # Closing Windows
$RemoveWindow.Close()
})
$ConfButtonN = new-object System.Windows.Forms.Button # Creating "no" button
$ConfButtonN.Location = '180, 80'
$ConfButtonN.Size = '100, 40'
$ConfButtonN.Text = 'NO'
$ConfButtonN.Add_Click({
$RemoveWindowConf.Close()
Write-Log "Canceled Confirmation for Deletion" #Log
})
$RemoveWindowConf.Controls.Add($ConfButtonY)
$RemoveWindowConf.Controls.Add($ConfButtonN)
$RemoveWindowConf.ShowDialog()
} else {
Write-Host "Please choose a Computer from the List!" # Informing user if they haven't changed from "<None>"
Write-Log "Selected device is <None>" #Log
}
})
$RemoveWindow.AcceptButton = $DeleteButton #Pressing enter will be the same as clicking on "Delete"
$RemoveWindow.Controls.Add($DeleteButton) #Adding the button to the Window
Write-Log "Creating Cancel Button for Main Delete Window" #Log
$DelCancelButton = new-object System.Windows.Forms.Button # Pressing Button that will close the deletion window
$DelCancelButton.Location = '220, 100'
$DelCancelButton.Size = '100, 40'
$DelCancelButton.Text = 'Cancel'
$DelCancelButton.Add_Click({ #Runs when button is clicked
$RemoveWindow.Close()
})
$RemoveWindow.Controls.Add($DelCancelButton)
Write-Log "Showing Window..." #Log
$RemoveWindow.ShowDialog()
}
}
class Leihgeraete{ #Examples
[string]$ComputerName #Example
[datetime]$SinceWhen #1.1.2023
[datetime]$UntilWhen #2.2.2023
[string]$Model #Example
[bool]$InUse #true or false
[string]$UsedBy #Example
[string]$SerialNumber #SNRAD9012
[string]$Owner #Example
[string]$InstallHinweis #Example
[string]$BookHinweis #Praktikant
Leihgeraete($ComputerName, $Model, $SerialNumber, $Owner, $InstallHinweis){ # Function for creating new Leihgeraete Object
$this.ComputerName = $ComputerName
$this.Model = $Model
$this.SerialNumber = $SerialNumber
$this.Owner = $Owner
$this.InstallHinweis = $InstallHinweis
Write-Log "[Class:Leihgeraete] Created new Leihgeraet" #Log
}
}
$Manager = [Manager]::new() # Creating Manager
Write-Log "Created Manager" #Log
Test
$Manager.AddDevice("Name","Model","SN","Own","Hinw")
$Manager.AddDevice("Namea","Modeaal","SNa","Owan","Hinwa")
I tried using different ways but none of them was fitting for my needs.
I also tried starting an extra job for adding the System.Windows.Forms but this resulted in my GUI elements also not working.
</details>
# 答案1
**得分**: 0
这是PowerShell中的一个错误:https://github.com/PowerShell/PowerShell/issues/2074
在那里的点源解决方法对我有效,但仅适用于ISE,而不适用于VS Code,所以如果使用ISE而不是VS Code可以的话,你可以使用它。
所以你可以创建另一个脚本文件,其中只包含以下内容:
Add-Type -AssemblyName 'System.Windows.Forms'
然后将该文件点源到你的类方法的顶部,如下所示:
AddDevice() { # 这个函数只是使用给定的数据创建一个新设备
. .\AddType.ps1
Write-Log "Starting AddWindow GUI creation..."
$AddWindow = New-Object System.Windows.Forms.Form
方法的其余部分.......
这目前只在当前目录下有效,但你可以将那个点源文件放在任何你想要的地方。
<details>
<summary>英文:</summary>
This is a bug in PowerShell: https://github.com/PowerShell/PowerShell/issues/2074
The workaround on there for dot sourcing worked for me, but only in ISE, not VS code, so you could use that, if using ISE instead of VS Code is ok.
So you create another script file with literally just this in it:
Add-Type -AssemblyName 'System.Windows.Forms'
then add that file dot sourced to the top of your class methods like:
AddDevice() { # This function simply creates a new device with the given data
. .\AddType.ps1
Write-Log "Starting AddWindow GUI creation..."
$AddWindow = New-Object System.Windows.Forms.Form
rest of method.......
That currently just works off the current directory, but you could keep that dot sourced file where ever you want.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论