Convert BodyStream in MSMQ to text/XML via PoSH? - powershell

What I'm trying to do: PEEK multiple MSMQ messages (not RECEIVE) using PowerShell, then return the contents of BodyStream in XML format (it appears to be in Decimal) so that I can shred the XML in the message and return information from within it.
We're trying to look and see what's still in the queue, what they have in common, what the most recent values in the XML are, etc. I've gone looking which is how I've gotten this far, but I haven't even figured how to peek multiple messages yet.
Here's basic code that will PEEK the first message in the "mybundles" private queue - ideally I'd like to do many more, maybe even the entirety (though again, without pulling them off the queue)
[Reflection.Assembly]::LoadWithPartialName("System.Messaging")
$queue = new-object System.Messaging.MessageQueue "FormatName:DIRECT=OS:servername\private$\mybundles"
$queue.Formatter.TargetTypes = ,[string]
$peekmsg = $queue.Peek()
[string]$sr = $peekmsg.BodyStream.ToArray()
$sr
When I do this, it returns a string of numbers, which is a decimal representation of the text I want. How do I change that string of numbers (or straight from BodyStream to text/XML?

Looks like you do this:
$peekmsg = $queue.Peek()
$sr= $peekmsg.BodyStream.ToArray()
$enc = [System.Text.Encoding]::ASCII
$enc.GetString($sr)
I think I'd just do a foreach loop, once I figure out how to PEEK multiple.

Related

Translating PS script without psd1 file

I'm a casual code writer. I'm in the self-assigned thread to create a script to install a software only available as an exe file for Windows and customize a bit some defaults stored in an xml file. This is a step/step process for me, each one being through big reading on the net and many trials. Being ATM at 5% estimated of the travel an (other :-( ) idea hit my mind : making the job also for English speaking people in addition to French, and publish the script so that any other can easily add their own language strings for messages. I discovered the MS scripts internationalization way that uses DATA section(s), psd1 files and some related commands.
My goal is to supply a single ps1 file, dot. My latest idea, based on what I recently read, was to have all the strings in the ps1 file, then based on $PSUIlocale export/create a temporary .\LG-lg\SetupThisSoft.psd1 I could Import-LocalizedData... what I guess is stupid (why export when we have the strings within the file?).
Do you have any idea to reach the goal? I now have some (better?) idea, using an array of yet-translated-locales, e.g. $AvailLng = "fr-FR","en-EN" then having one DATA section for each $Item I could ForEach test against $PSUILocale, but I have no idea how to "point"/"enable" the good DATA section. "en-EN" would be the last $Item as a default/fallback when $PSUILocale doesn't match any previous $Item...
Thanks for ideas
Store your Data sections in a hashtable and use the locale identifier (fr-FR, en-US etc.) as the key:
# Store messages for multiple languages in $localizedMessages
$localizedMessages = #{
'en-US' = Data {
ConvertFrom-StringData #'
Error = an error occurred
Success = something wonderful happened
'#
}
'fr-FR' = Data {
ConvertFrom-StringData #'
Error = une erreur est survenue
Success = quelque chose de merveilleux est arrivé
'#
}
}
$defaultLanguage = 'fr-FR'
# Assign the appropriate language version to the variable that holds the messages for later use
$Messages = if($localizedMessages.ContainsKey($PSUICulture)){
$localizedMessages[$PSUICulture]
} else {
# If we don't have localized messages for the current culture, we fall back to our default language
$localizedMessages[$defaultLanguage]
}
# ...
# This will now throw a different error message based on the current UI culture
Write-Error $Messages['Error']

Handle POST data sent as array

I have an html form which sends a hidden field and a radio button with the same name.
This allows people to submit the form without picking from the list (but records a zero answer).
When the user does select a radio button, the form posts BOTH the hidden value and the selected value.
I'd like to write a perl function to convert the POST data to a hash. The following works for standard text boxes etc.
#!/usr/bin/perl
use CGI qw(:standard);
sub GetForm{
%form;
foreach my $p (param()) {
$form{$p} = param($p);
}
return %form;
}
However when faced with two form inputs with the same name it just returns the first one (ie the hidden one)
I can see that the inputs are included in the POST header as an array but I don't know how to process them.
I'm working with legacy code so I can't change the form unfortunately!
Is there a way to do this?
I have an html form which sends a hidden field and a radio button with
the same name.
This allows people to submit the form without picking from the list
(but records a zero answer).
That's an odd approach. It would be easier to leave the hidden input out and treat the absence of the data as a zero answer.
However, if you want to stick to your approach, read the documentation for the CGI module.
Specifically, the documentation for param:
When calling param() If the parameter is multivalued (e.g. from multiple selections in a scrolling list), you can ask to receive an array. Otherwise the method will return the first value.
Thus:
$form{$p} = [ param($p) ];
However, you do seem to be reinventing the wheel. There is a built-in method to get a hash of all paramaters:
$form = $CGI->new->Vars
That said, the documentation also says:
CGI.pm is no longer considered good practice for developing web applications, including quick prototyping and small web scripts. There are far better, cleaner, quicker, easier, safer, more scalable, more extensible, more modern alternatives available at this point in time. These will be documented with CGI::Alternatives.
So you should migrate away from this anyway.
Replace
$form{$p} = param($p); # Value of first field named $p
with
$form{$p} = ( multi_param($p) )[-1]; # Value of last field named $p
or
$form{$p} = ( grep length, multi_param($p) )[-1]; # Value of last field named $p
# that has a non-blank value

powershell google sheets restmethod post

I'm working on a powershell script to get information from a google sheet, change data and then update the info in the google sheet. I have it working were i can get the data, but i'm having a issues posting the data back. Right now im only requesting one row as of now. it comes back as a array of array object in $file. To change the data i do $file[0][2]. This will change the data in column two to what ever i want.
What does the body need to look like? i have tried different things but keep getting a bad request error. My message body looks like this;
$body = #{
"values" = $File
}
EDIT: So i guess use you need to add the "?valueInputOption=RAW" to the end of the URL. So i'm able to change the data, but i still cant use a array to update the whole row. What is the best way to update the whole row?
Use spreadsheets.values.update to update values in a spreadsheet. Check the Writing guide docs for more info and code samples.
Did you try to convert the data you return to JSON format? Most API's (as far as i've seen them) mostly like there data back in JSON.
try this:
$data = $body | ConvertTo-Json
and return $data to google sheets.
i might be wrong but have only done this a few times too.

Perl XML::SAX - character() method error

I'm new to using Perl XML::SAX and I encountered a problem with the characters event that is triggered. I'm trying to parse a very large XML file using perl.
My goal is to get the content of each tag (I do not know the tag names - given any xml file, I should be able to crack the record pattern and return every record with its data and tag like Tag:Data).
While working with small files, everything is ok. But when running on a large file, the characters{} event does partial reading of the content. There is no specific pattern in the way it cuts down the reading. Sometimes its the starting few characters of data and sometimes its last few characters and sometimes its just one letter from the actual data.
The Sax Parser is:
$myhandler = MyFilter->new();
$parser = XML::SAX::ParserFactory->parser(Handler => $myhandler);
$parser->parse_file($filename);
And, I have written my own Handler called MyFilter and overridding the character method of the parser.
sub characters {
my ($self, $element) = #_;
$globalvar = $element->{Data};
print "content is: $globalvar \n";
}
Even this print statement, reads the values partially at times.
I also tried loading the Parsesr Package before calling the $parser->parse() as:
$XML::SAX::ParserPackage = "XML::SAX::ExpatXS";
Stil doesn't work. Could anyone help me out here? Thanks in advance!
Sounds like you need XML::Filter::BufferText.
http://search.cpan.org/dist/XML-Filter-BufferText/BufferText.pm
From the description "One common cause of grief (and programmer error) is that XML parsers aren't required to provide character events in one chunk. They can, but are not forced to, and most don't. This filter does the trivial but oft-repeated task of putting all characters into a single event."
It's very easy to use once you have it installed and will solve your partial character data problem.

How can I write a binary Stream object to a file in PowerShell?

I think I've tried every wrong way, and those few that don't just give ugly error messages write a garbled file that cannot be opened (you can still see the JFIF in it, but the jpeg magic smoke has been lost).
The Stream itself is $contactInfo.Get_Item("Photo"). I think I need to do something like this:
$br = new-object System.IO.BinaryReader $contactInfo.Get_Item("Photo")
But past that, I don't know what to do. I've tried Googling, but I'm not even sure what I'm looking for to be quite honest.
The type of the Stream object is Microsoft.Lync.Model.UCStream.
I don't have access to this particular type (UCStream) but in general you would write this in PowerShell like so:
$br = new-object io.binaryreader $contactInfo.Get_Item("Photo")
$al = new-object collections.generic.list[byte]
while (($i = $br.Read()) != -1)
{
$al.Add($i)
}
Set-Content photo.jpeg $al.ToArray() -enc byte