PowerShell SMLets - Cannot Create an instance of an abstract class - class

I am using SMLets (A collection of cmdlets that work with System Center) for PowerShell to create an object of a class. I know I am not supposed to create objects of abstract classes, but I am not sure what other class I could possible select. I am trying to create a group in System Center Service Manager, and the class for a configuration item group as far as I can tell is the one I am entering...
My code is:
#Get the name of the class I want to create an object of and store it in a variable
$groupClass = Get-SCSMClass -Name "Microsoft.SystemCenter.ConfigItemGroup$"
#Return the variable stored to ensure this part is working (Debug purposes)
$groupClass
#Get the active status of an object and store it in a variable
$objStatus = Get-SCSMEnumeration -Name System.ConfigItem.ObjectStatusEnum.Active
#Return the variable stored to ensure this part is working (Debug purposes)
$objStatus
#Create the object stored in my class variable and modify the DisplayName and ObjectStatus properties.
New-SCSMObject -Class $groupClass -PropertyHashtable (#{DisplayName = "Test"; ObjectStatus = $objStatus;}) -Debug -Verbose
Once I got this code working my idea was to read from a csv file containing a list of all the groups and loop the creation process. However, I keep getting the error: "Cannot create objects of an abstract class"
Am I using the incorrect class to create a group? If so, what is the correct class to select? Is there a more efficient method to do this? Any ideas at all please share, thank you in advance :)

Related

Access related model fields from ModelAdmin actions for exporting to excel

I am desperately waiting for someone attention to get my question answered.... please help..
ModelAdmin model has to export to Excel action method.
I need to access related model fields in action method. That means I can not pass any arguments therefore I tried relatedmodel_set but ModelAdmin action method shows memory location and fails when I try to access values through attributes:
<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager..RelatedManager object at 0x7f8eea904ac0>
model.py
class EnrolStudent(models.Model):
def get_trn_activity(self):
return self.studenttraininactivities_set
class StudentTraininActivities(models.Model):
trainin_activities = models.ForeignKey(EnrolStudent,
on_delete=CASCADE, null=True )
<other fields...>
admin.py
#admin.register(EnrolStudent)
class EnrolAdmin(admin.ModelAdmin):
form = CityInlineForm
inlines = [CohortTraininActivitiesInline]
...
actions = [export_as_txt_action_0120("File NAT00120 data Export"
, fields=['information_no', 'get_trn_activity',
'student_enrol__student_code'])]
I need to access related model fields to export to excel.
I can not pass parameter to get_trn_activity as you have noticed.
Therefore selected rows only data from Django admin change_list page will only need bit of work using its queryset in actions method used in separate actions.py file that I can do!
Please help me with this issue. I am new to Python / Django.
I also tried property decorator in related model then access in a method in main model then call it inside action but same problem with memory address not the direct value and then how to get data of memory location here .... I don't know.
If I can access the related fields then I can do it no issue.
Another question:
I had same situation with model/related model before, but they were connected through OneToOneField relationship and I was able to use dundor to access related model fields but in this case of ForiegnKey relationship I can not see related model in queryset.
In other case this is what I can do easily; here cohortdetails is related model and when I debug I saw it was listed in queryset that was great.
actions = [export_as_txt_action_0080("File NAT00080 txt Export",
fields=['rto_student_code', 'first_name', 'family_name'
,'cohortdetails__highest_school__highestschool_levelcode',
'cohortdetails__cohort_gender'
, 'cohortdetails__student_dob' ])]

Use a custom class defined in a different file as type in Powershell

I want to use a custom class I declared in a different file as a type:
emailhelper.ps1
class EmailInfo
{
[string]$subject;
[string]$body;
[System.Collections.Generic.List[string]]$distributionList;
}
myfile.ps1
."$PSScriptRoot\.\emailhelper.ps1"
class MyClass
{
[EmailInfo]$startEmailInfo;
...
MyClass([EmailInfo] $info)
{
...
}
}
But it seems not to find it:
En C:\xxx\yyyy\myscript.ps1: 64 Carácter: 6
+ [EmailInfo]$info;
+ ~~~~~~~~~ Cannot find the type [EmailInfo].
The strange thing is that I can create new objects without any problem:
$emailInfo = New-Object EmailInfo;
So the problem seems to be related to using "EmailInfo" as a type.
Finally, if I add "EmailInfo" to the myscript.ps1, that is, the same file where the class is being used, then I can use it as a type...
So, how can I use a class defined in a different file as a type?
The simplest solution is to use the using keyword, at the very beginning of your script :
using module .\path\to\your\Module.psm1
Path can be relative from your current file.
To prevent caching problem, use powershell.exe .\script.ps1 to execute it, even in the PoweShell ISE console.

Generic collection as parameters

I would like to use a generic collection as a parameter type for a PowerShell function like so:
function Execute-Tokenlist
{
param([System.Collections.Generic.List[WTToken]]$Tokenlist)
}
[WTToken] is just a custom type.
I create a new generic collection list with WTToken objects:
$TokenList1 = New-Object -TypeName System.Collections.Generic.List[WTToken]
But when I try to call the function
Execute-Tokenlist -Tokenlist $TokenList1
the result is a ParameterBindingArgumentTransformationException because PowerShell turns System.Collections.Generic.List`1[WTToken] into a new type:
System.Collections.Generic.List`1[[WTToken, TokenListeAuswerten.ps1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]
So it adds the script name as an assembly name to the type name.
My question is: How can I prevent that PowerShell does these kind of type transformation?
I know I could use Object as a parameter type but I don't like giving up type checking for no good reason.
I found the solution and (of course) it has a simple explanation.
Powershell includes in the full name of any type thats based on a class definition the path of the Ps1 file that contains the class definition or just "\powershell" if the definition is not in a ps1 file.
My mistake was that I was opening a new script window inside the ISE and put in the code for defining the class.
Then I tried to put an object based on that class in a generic collection that was already defined inside a ps1 file and has an Add method that excpects objects with a type that includes a ps1 file. Since the new object type name didn't contain that ps1 path I got that error messages that didn't make sense to me (now it does).
Here is the complete PowerShell script code again:
class WTToken
{
[String]$Type
[String]$Name
[Bool]$Value
}
$TokenList = [System.Collections.Generic.List[WTToken]]::new()
$Token = [WTToken]::new()
$TokenList.Add($Token)
$TokenList.GetType().FullName
Start the ISE, paste in that code and save it into a ps1 file, eg. test.ps1 and run it with F5.
Now open a new script window and paste in the following Powershell code:
class WTToken
{
[String]$Type
[String]$Name
[Bool]$Value
}
$Token = [WTToken]::new()
$TokenList.Add($Token)
Run this and an error message should appear.

creating GUI forms without variables

I am trying to find a way to create a form in PowerShell without using any variables unless they are temporarily or virtually assigned. I want to be able to run a command similar to this:
(New-Object System.Windows.Forms.Form).ShowDialog()
where I can enter in a code into an event that is triggered once the form is created. That event will then be responsible for creating all the objects and other events inside the form. Once the form is launched, I will not need any variables accept for the ones that are virtually assigned within the events.
This to avoid using too much system resources from assigning and endless amount of variables for each object in the form. The script that I am currently working on in PowerShell is very possibly going to be really big, and even if it is not a very large script, efficiency and clean code is always the key to writing a good program or script.
add-type -ass System.Windows.Forms
$x = (New-Object System.Windows.Forms.Form)
$x.Text = 'Message Box'
$x.Size = '300,150'
$x.Font = $x.Font.Name + ',12'
$x.Controls.Add((New-Object System.Windows.Forms.Label))
$x.Controls[-1].Size = $x.Size
$x.Controls[-1].Text = 'Here is a message for you'
$x.ShowDialog()
Remove-Variable x
It is very possible to access these objects still with the exact same kind of access when you define each object with a variable. It cost me many hours of research and just simply attempting random commands to find out how to do this. Here is all the commands you may need to relearn if you are interested in my solution:
# create item in form:
$x.Controls.Add((New-Object System.Windows.Forms.Button))
# access the last created item in the form:
$x.Controls[-1]
# change it's name to identify it easier
$x.Controls[-1].Name = 'button1'
# access the item by it's new name:
$x.Controls['button']
# delete the item by it's name:
$x.Controls.Remove($x.Controls['button1'])
If your familiar with form creation in PowerShell then this should all make sense to you and you should be familiar with how the rest of it works. Also, another note to make for those who are interested in what I am trying to do is that any of these commands can be done within an event by replacing $x with $this. If it is inside an event of an object inside the "controls" section of the form, then you would use $this.parent.
This is exactly what I mean by having the ability to create a form with virtually no variables. The only problem I am having with this is that I am unsure how to assign an event and call the method ShowDialog() at the same time.
I found an a very interesting solution to this, however I am not sure to what the limits are to this solution and it dose not quite work in the way that I would personally like it to.
file.ps1:
add-type -ass System.Windows.Forms
$x = (New-Object System.Windows.Forms.Form)
$x.Text = 'Message Box'
$x.Size = '300,150'
$x.Font = $x.Font.Name + ',12'
$x.Controls.Add((New-Object System.Windows.Forms.Label))
$x.Controls[-1].Size = $x.Size
$x.Controls[-1].Text = 'Here is a message for you'
$x
remove-variable x
command to execute the code:
(iex(Get-Content 'file.ps1'|out-string)).ShowDialog()

Failed to set iTunes track properties using Powershell

I used to use vbscripts to automate tasks such as adding mp3, changing genre, comments for tracks in iTunes.
I am now trying to create powershell scripts to do the same. I can added mp3 to iTunes, but I failed to change the properties of the track.... I don't know what I've missed.... The following is a sample of the powershell codes to change the Genre and the error said the property "genre" does not exist.
$iTunes = New-Object -com "iTunes.Application"
$library = $iTunes.LibraryPlaylist
$iTrack = $library.addfile("c:\temp\test.mp3")
$iTrack.tracks.Genre = "test"
However, I can see the property using $iTrack.tracks | get-member
Genre Property string Genre () {get} {set}
Thanks to anyone who could help..
I found two ways (there's more) to set properties.
Force the track to an array and set the properties of the first item
#($iTrack.Tracks)[0].Genre = "test"
Set properties by item name (which is kind of occurred when the object you have is already the one you want to set)
$iTrack.Tracks.ItemByName('song name').Genre = "test"