PowerShell trying to convert to an integer instead of a string - excel

My problem is that PowerShell wants to convert "=" into an integer, when trying to use it to make a new string. I made sure that my resulting variable would also be a string. Here's my task:
I have a little Excel table like this:
___________|VLANID1|VLANID2|VLANID3|
SwitchName1| 1-7| 12-16| 8-11| ← Ports 1-7 of Switch1 are configure for VLAN1...
SwitchName2| 1-7| 12-16| 8-11|
Out of this table I want to save each port in an .ini file with the VLAN it is configured too, aka:
[SwitchName1]
1=VLANID1
2=VLANID3
...
And here's my code which I loop until there are no ports, and then no more switches.
$split = $global:Ports -split("-") #$Ports is the Value with the saved excel cell (7-11)
$split[0]..$split[1] | ForEach-Object {
$vlan = $global:Switches.Cells.Item(1, $global:SSpallte).Text
[string]$inistring = "`n" + $_ + "=" + $vlan #<- Here it tries to convert "=" into integer
Add-Content -Path $global:portsini -Value $inistring
}
I even tried converting every variable which I use to make $inistring to a string before, it still doesn't work. Also, both $_ and $vlan have a Value and are not $null.
The Error states that "=" cannot be converted into the type "System.Int32".

So, im not quite sure what the problem was, but my way to solve it was to restart my environment. I am programming in the PowerShell ISE which I have sometimes seen "caching" variables. This restart of the ISE made the program work again.
And no, I didn't change anything beforehand.
In the end I'm happy that my problem is no more, but I'm still wondering why the error got triggered by the "=".

Related

PowerShell Dynamic Creation of ADUsers from imported Excelsheet

first of all, i want to say, that i'm very, very new to PowerShell. These are the first PS-scripts i wrote.
I'm currently working on a PS-Script for AD-Administration. Currently the Scripts for Adding/Deleting SmbShares, Adding or removing Users from Groups, and so on, are already done.
I already had a working script for creating the users in AD, but it wasn't dynamic, as in hard coded variables that all would have to be entered into a new-ADUser command. As the code will be used for more than one specific set of parameters, it has to be dynamic.
I'm working with Import-Excel and found a great function here, but I'm having two problems wih this function.
$sb = {
param($propertyNames, $record)
$propertyNames | foreach-object -Begin {$h = #{} } -Process {
if ($null -ne $record.$_) {$h[$_] = $record.$_}
} -end {New-AdUser #h -verbose}
}
Use-ExcelData -Path $Path -HeaderRow 1 -scriptBlock $sb
The dynamic part of this is, that the table headers will be used as the parameternames for New-ADUser. Only thing one needs to change if the amount of parameters needed changes is add or delete a column in the excel sheet. The column header always needs the same name as the parameter of New-ADUser.
Screenshot of excel table
My Problem now is the "Type" Header i've got at column A. It is needed to specify the type of the user for adding the user to specific ADGroups. But due to the function above using all headers as parameters this doesn't work.
Has anyone an idea how to change the function $sb so that it starts with the second column? I've tried aroung with skip 1 and tried a lot of other workarounds, but with my non-experience nothing ssemed to come close to what i need.
SOLVED PROBLEM BELOW: added -DataOnly to Use-ExcelData and now it works.
The second problem would be, that the function does not stop trying to create users once there are no more values for the parameters. For trying around i deleted the column "Type". In the example of trying to create the two users testuser and testuser2, Powershell creates the users with no problems but then asks for a name for a new-ADUser.
AUSFÜHRLICH: Ausführen des Vorgangs "New" für das Ziel "CN=Test User,CN=Users,DC=****,DC=**".
AUSFÜHRLICH: Ausführen des Vorgangs "New" für das Ziel "CN=Test2 User2,CN=Users,DC=****,DC=**".
Cmdlet New-ADUser an der Befehlspipelineposition 1
Geben Sie Werte für die folgenden Parameter an:
Name:
Thank you in advance, sorry for my english and please tell me if I did something wrong forumwise.
I see you I would save the excel sheet as a CSV file and then import it. It's faster and easier to consume. The headers become your parameter names and the import behaves like any other object.
$csvData = Import-csv -path <path to csv file>
From here, iterate the rows and access the values as properties of the row. No need to import the data into a hashtable, it's already accessible with property names defined by the header row.
foreach ($row in $csvData) {
Write-Host $row.Name
Write-Host $row.Path
}
Once the loop reaches the end of the file, it stops trying to create users.
FYI, The use of single letter variables is going to make your code very difficult to maintain. My eyes hurt just looking at it.

PowerShell - Import Excel then Export CSV without using Excel or COM

I am developing a PowerShell script to import an Excel file and output the data to a flat file. The code that I have below works fine except that it fails to preserve leading zeros; when the CSV file is opened in a text editor, the leading zeros are not present. (Leading zeros are necessary for certain ID numbers, and the ID numbers are stored in Excel using a custom format.) Does anyone have any thoughts on how to get the ImportExcel module to preserve the leading zeros, or, perhaps another way of getting to the same goal? I would like to do this without using the COM object and without having to install Excel on the server; that's why I've been trying to make the ImportExcel module work.
$dataIn = filename.xlsx ; $dataOut = filename.csv
Import-Excel -Path $dataIn | Export-Csv -Path $dataOut
I presume you're using the ImportExcel module?
I just did this and it worked. I created a spreadsheet like:
Name ID1 ID2
Steven 00012345 00012346
I gave them a custom number format of 00000000 then ran:
Import-Excel .\Book1.xlsx | Export-Csv .\book1.csv
When looking at the csv file I have both ID numbers as quoted strings:
"Name","ID1","ID2"
"Steven","00012345","00012346"
Is there anything else I need to do to reproduce this? Can you give the specifics of the custom number format?
Also withstanding your answer to above. You can modify the properties of each incoming object by converting them to strings. Assuming there's a fixed number of digits you can use the string format with the .ToString() method like:
(12345).ToString( "00000000" )
This will return "00012345"...
So redoing my test with regular numbers (no custom format):
$Input = #(Import-Excel \\nynastech1\adm_only\ExAdm\Temp\Book1.xlsx)
$Input |
ForEach{
$_.ID1 = $_.ID1.ToString( "00000000" )
$_.ID2 = $_.ID2.ToString( "00000000" )
}
This will convert ID1 & ID2 into "00012345" & "00012345" respectively.
You can also use Select-Object, but you might need to rename the properties. If you are interested I can demo that approach.
Note: the #() wrapping in my example is because I only have the 1 object, and is partly force of habit.
Let me know how it goes.

Find and replace a specific string within a specific file type located in wildcard path

Problem:
Update a specific string within numerous configuration files that are found within the subfolders of a partial path using PowerShell.
Expanded Details:
I have multiple configuration files that need a specific string to be updated; however, I do not know the name of these files and must begin my search from a partial path. I must scan each file for the specific string. Then I must replace the old string with the new string, but I must make sure it saves the file with its original name and in the same location it was found. I must also be able to display the results of the script (number of files affected and their names/path). Lastly, this must all be done in PowerShell.
So far I have come up with the following on my own:
$old = "string1"
$new = "string2"
$configs = Get-ChildItem -Path C:\*\foldername\*.config -Recurse
$configs | %{(Get-Content $_) -Replace $old, $new | Set-Content $_FullName
When I run this, something seems to happen.
If the files are open, they will tell me that they were modified by another program.
However, nothing seems to have changed.
I have attempted various modifications of the below code as well. To my dismay, it only seems to be opening and saving each file rather than actually making the change I want to happen.
$configFiles = GCI -Path C:\*\Somefolder\*.config -Recurse
foreach ($config in $configFiles) {
(GC $config.PSPath) | ForEach-Object {
$_ -Replace "oldString", "newString"
} | Set-Content $config.PSPath)
}
To further exasperate the issue, all of my attempts to perform a simple search against the specified string seems to be posing me issues as well.
Discussing with several others, and based on what have learned via SO... the following code SHOULD return results:
GCI -Path C:\*\Somefolder\*.config -Recurse |
Select-String -Pattern "string" |
Select Name
However, nothing seems to happen. I do not know if I am missing something or if the code itself is wrong...
Some questions I have researched and tried that are similar can be found at the below links:
UPDATE:
It is possible that I am being thwarted by special characters such as
+ and /. For example, my string might be: "s+r/ng"
I have applied the escape character that PowerShell says to use, but it seems this is not helping either.
Replacing a text at specified line number of a file using powershell
Find and replacing strings in multiple files
PowerShell Script to Find and Replace for all Files with a Specific Extension
Powershell to replace text in multiple files stored in many folders
I will continue my research and continue making modifications. I'll be sure to notate anything that get's me to my goal or even a step closer. Thank you all in advance.

Replace strings in text files with string literals and file names in powershell

My google-fu has failed me, so I'd love to get some help with this issue. I have a directory full of markup files (extension .xft). I need to modify these files by adding string literals and the filename (without the file extension) to each file.
For example, I currently have:
<headerTag>
<otherTag>Some text here </otherTag>
<finalTag> More text </finalTag>
What I need to end up with is:
<modifiedHeaderTag>
<secondTag> filenameGoesHere </secondTag>
<otherTag>Some text here </otherTag>
<finalTag> More text </finalTag>
So in this example,
"<modifiedHeaderTag>
<secondTag>"
would be my first string literal (this is a constant that gets inserted into each file in the same place),
filenameGoesHere
would be the variable string (the name of each file) and,
"</secondTag>"
would be my second constant string literal.
I was able to successfully replace text using:
(Get-Content *.xft).Replace("<headerTag>", "<modifiedHeaderTag>")
However, when I tried
(Get-Content *.xft).Replace("<headerTag>", "<modifiedHeaderTag> `n
<secondTag> $($_.Name) </secondTag>")
I just got an error message. Replacing $($_.Name) with ${$_.Name) also had no effect.
I've tried other things, but this method was the closest that I had gotten to success. I would appreciate any help that I can get. It's probably simple and I'm just not seeing something due to inexperience with Powershell, so a helping hand would be great.
If the above isn't clear enough, I'd be happy to provide more info, just let me know. Thanks everyone!
Here's my approach, assuming you have all of the XFT's in one folder and you want to write the updates back to the same file:
$path = "C:\XFTs_to_Modify"
$xfts = Get-ChildItem $path -Include "*.xft"
foreach ($xft in $xfts) {
$replace = "<modifiedHeaderTag>
<secondTag> $($xft.Name) </secondTag>"
(Get-Content *.xft).Replace("<headerTag>", $replace) | Set-Content $xft.FullName -Force
}

Trying to Export a CSV list of users using Active Directory Module for Windows Powershell

So the below is where I'm at so far:
import-module activedirectory
$domain = "ourdomain"
Get-ADUser -Filter {enabled -eq $true} -Properties whenCreated,EmailAddress,CanonicalName |
select-object Name,EmailAddress,CanonicalName,whenCreated | export-csv C:\Data\test.csv
Unfortunately, when I run the above I get dates in two different formats in the CSV, e.g.:
01/01/2017
1/01/2017 8:35:56 PM
The issue this poses is that there isn't really a clean way to sort them. Excel's formatting doesn't change either of these formats to be more like the other, both because of the inclusion of time in one and not the other, and because the time-inclusive format doesn't use trailing zeroes in the single digit numbers, but the time-exclusive format does.
We have an existing script that captures users using the LastLogonTimestamp attribute that does this correctly by changing the bottom line to the following:
select-object Name,EmailAddress,CanonicalName,#{Name="Timestamp"; Expression={[DateTime]::FromFileTime($_.whenCreated).ToString('yyyy-MM-dd_hh:mm:ss')}}
For some reason this expression runs properly when we query the LastLogonTimestamp attribute, but when we run this version querying the whenCreated attribute, we get an entirely blank column underneath the Timestamp header.
I'm not particularly knowledgeable about PowerShell itself, and my colleague who had found the original script for the LastLogonTimestamp just found it online and adapted it as minimally as possible to have it work for us, so I don't know if something in this line would work properly with one of these attributes and not the other. It seems strange to me though that two attributes using dates in the same program would store them in different formats though, so I'm not convinced that's it.
In any case, any help anyone can offer to help us get a uniform date format in the output of this script would be greatly appreciated - it needn't have the time included if it's easier to do away with it, though if they're equally easy we may as well keep it.
whencreated is already a [DateTime]. Notice the difference between the properties when you run something like this:
Get-ADUser TestUser -Properties lastlogon,whenCreated | select lastlogon,whenCreated | fl
(Get-ADUser TestUser -Properties lastlogon).lastlogon | gm
(Get-ADUser TestUser -Properties whenCreated).whenCreated | gm
This means that you don't have to convert to a DateTime before running the toString() method.
select-object #{Name="Timestamp"; Expression={$_.whenCreated.ToString('yyyy-MM-dd_hh:mm:ss')}}

Resources