Generate a list of PowerShell Cmdlets:
"Name`tSynopsis`tDescription`tFile"
ls -recurse $PSHOME *-Help.xml | foreach {
$fileName = $_.Name
$help = [xml](gc $_.fullName)
$help.helpitems.command | foreach {
write-output ([string]::format("{0}`t{1}`t{2}`t{3}",$_.details.name.trim(),$_.details.description.get_InnerText().trim(),$_.description.get_InnerText().trim().replace("`n", " "),$fileName))
}
}
Generate a list of Aliases:
"Name`tDefinition"
get-alias | sort -property Name | select Name, Definition |% {
write-output ([string]::format("{0}`t{1}", $_.Name,$_.Definition))
}
Each output is tab delimited.
Just some random development ramblings mostly related to the Microsoft .NET platform.
Monday, December 10, 2007
Sunday, December 2, 2007
Generate .NET Guid
To generate a .NET guid in PowerShell:
Write-Host ([System.Guid]::NewGuid())
Or to generate a bunch of guids:
1..30 |% { Write-Host ([System.Guid]::NewGuid()) }
Write-Host ([System.Guid]::NewGuid())
Or to generate a bunch of guids:
1..30 |% { Write-Host ([System.Guid]::NewGuid()) }
Counting # of matching lines in file
I wanted to scan a large number XML files and determine which ones had more than 20 elements of a particular type. Here was the PowerShell command-line I used to report on files that contains more than 20 "" elements:
gci *.xml |% {$fn=$_.name; gc $_ | where {$_ -match ""} |% {$count = 0}{++$count}{if ($count -gt 20) {$fn}}}
An easier, but not very good for performance if a large number of files are involved is:
gci f_*.xml | select-string "" | group filename | where {$_.count -gt 20} | select count, name
gci *.xml |% {$fn=$_.name; gc $_ | where {$_ -match "
An easier, but not very good for performance if a large number of files are involved is:
gci f_*.xml | select-string "
Tuesday, November 6, 2007
PowerShell to report top 10 results from log file
Ever want to sift through a log file and report on the top 10 occurances of a certain field value? Here is a PowerShell script that will do just that.
I had a log file that contained an IP address in the third field (column index 2 since arrays start at zero in PowerShell). I wanted to know what were the top 10 IPs that were logs. I could call this script like:
./ipcount.ps1 logfile.log 2
When using huge log files, don't forget if you want to redisplay, but not recompute, the results, you can "dot source" the script like:
. ./ipcount.ps1 logfile.log 2
Then $result will always hold the last set of results. Here is the script (3 lines...middle line is really long):
param($file,$index)
$result = gc $file | foreach {$hash=@{}}{$hash[$_.split(',')[[int]$index]] += 1}{$hash.getenumerator()} | sort value -desc | select -first 10
$result
I had a log file that contained an IP address in the third field (column index 2 since arrays start at zero in PowerShell). I wanted to know what were the top 10 IPs that were logs. I could call this script like:
./ipcount.ps1 logfile.log 2
When using huge log files, don't forget if you want to redisplay, but not recompute, the results, you can "dot source" the script like:
. ./ipcount.ps1 logfile.log 2
Then $result will always hold the last set of results. Here is the script (3 lines...middle line is really long):
param($file,$index)
$result = gc $file | foreach {$hash=@{}}{$hash[$_.split(',')[[int]$index]] += 1}{$hash.getenumerator()} | sort value -desc | select -first 10
$result
Friday, November 2, 2007
URLs and System.IO.Path
Cool. I just found out that the .NET System.IO.Path static methods like GetFilename and GetDirectory work with internet URLs as well. I was wanting to get just the file name from a URL and the System.Uri class doesn't do this...but Path does. Now ain't that slick.
Friday, October 26, 2007
Finally...a use for .NET partial classes
When .NET 2.0 was released, partial classes was recognized as one of the top four cool new features (along with generics, anonymous methods, and iterators). After developing with 2.0 for some time now, I haven’t found a good reason to use partial classes (besides the Page class in ASP.NET that is created for you automatically). I do however recognize its importance for Visual Studio 2005 and how the auto-generated code and our own Page classes are created. Besides that, I just haven’t ran into a situation where I really needed it.
Recently I wrote some code where I stood up and cheered partial classes. If you ever used the .NET xsd.exe utility in .NET 1.1 to create a strong-typed class for an XSD file, you know that the tool created this handy set of classes for you to access the elements of an XML file. This was a good thing, but I would always end up writing several separate utility classes to provide a layer on top of, or along side of, the auto-generated class from xsd.exe. Although tempted at times, I couldn’t modify the auto-generated class file since I might regenerate it at a later time (I always did).
Much to my glee, xsd.exe in .NET 2.0 now creates partial classes! This now allows me to write separate class files and add properties and methods to the auto-generated ones from xsd.exe. This provides a nice separation/coupling from the xsd.exe generated code. Excellent!
I see a pattern here…for things that auto-generate code, partial classes are a welcome addition to .NET.
Recently I wrote some code where I stood up and cheered partial classes. If you ever used the .NET xsd.exe utility in .NET 1.1 to create a strong-typed class for an XSD file, you know that the tool created this handy set of classes for you to access the elements of an XML file. This was a good thing, but I would always end up writing several separate utility classes to provide a layer on top of, or along side of, the auto-generated class from xsd.exe. Although tempted at times, I couldn’t modify the auto-generated class file since I might regenerate it at a later time (I always did).
Much to my glee, xsd.exe in .NET 2.0 now creates partial classes! This now allows me to write separate class files and add properties and methods to the auto-generated ones from xsd.exe. This provides a nice separation/coupling from the xsd.exe generated code. Excellent!
I see a pattern here…for things that auto-generate code, partial classes are a welcome addition to .NET.
Friday, October 19, 2007
DataFormatString not working in GridView
I often use the DataFormatString in the .NET 2.0 GridView control. It seems like the DataFormatString property on a bound column is ignored unless you also set the column's HtmlEncode property to false (the default value is true).
.NET ToString() formatting help
Here is a useful 2-page cheat sheet on the various ToString() formatting options in the .NET Framework languages.
Download Here
Download Here
Wednesday, October 17, 2007
Clear Visual Studio "Recent Project" entries
Sometimes you want to clear all the "Recent Projects" from my Visual Studio Start Page. You can do this by removing registry values at the following locations in the registry:
To clear recent files:
HKCU\Software\Microsoft\VisualStudio\8.0\FileMRUList
To clear recent projects/solutions:
HKCU\Software\Microsoft\VisualStudio\8.0\ProjectMRUList
To clear recent files:
HKCU\Software\Microsoft\VisualStudio\8.0\FileMRUList
To clear recent projects/solutions:
HKCU\Software\Microsoft\VisualStudio\8.0\ProjectMRUList
Saturday, October 13, 2007
Regex.Replace
From Brian Davis:
The String.Replace function has been a valuable tool for years, allowing programmers to change strings by replacing a specific substring with another substring. While this is usually enough, the Regex.Replace function goes a step (ok, maybe 10 steps) further. It allows replacement of text using regular expressions. Not only can you define the text to replace using a regular expression, you can define what to replace it with using a replacement string containing special constructs which identify portions of the mathed text. A common example is the representation of a name. Let's say you have a name in a string like "John Doe", but you would really like to have "Doe, John". You could accomplish this with a few lines of code, splitting the string on a space and constructing a new string using the elements, or you could do it in one simple line:
This is a simplified example with a simple expression (we don't allow names like John J. Doe, John Boy Doe, John Doe, Jr., etc.), but it shows how using the Regex.Replace function can take several lines of code down to just a few. If we were to write a more complex expression, it would still require just one line of code in our application, whereas we may have to add dozens of lines of code with If...Else blocks or Select Case statements to accomplish complicated parsing.
Here's a look at some of the constructs that can be used in a Regex replacement string:
$& - matched text
$_ - original source string
$` - text before match
$' - text after match
${group_name} - text matched by named group
$1, $2 - text matched by numbered group
$$ - the literal "$"
The String.Replace function has been a valuable tool for years, allowing programmers to change strings by replacing a specific substring with another substring. While this is usually enough, the Regex.Replace function goes a step (ok, maybe 10 steps) further. It allows replacement of text using regular expressions. Not only can you define the text to replace using a regular expression, you can define what to replace it with using a replacement string containing special constructs which identify portions of the mathed text. A common example is the representation of a name. Let's say you have a name in a string like "John Doe", but you would really like to have "Doe, John". You could accomplish this with a few lines of code, splitting the string on a space and constructing a new string using the elements, or you could do it in one simple line:
strInput = Regex.Replace(strInput,"(? |
This is a simplified example with a simple expression (we don't allow names like John J. Doe, John Boy Doe, John Doe, Jr., etc.), but it shows how using the Regex.Replace function can take several lines of code down to just a few. If we were to write a more complex expression, it would still require just one line of code in our application, whereas we may have to add dozens of lines of code with If...Else blocks or Select Case statements to accomplish complicated parsing.
Here's a look at some of the constructs that can be used in a Regex replacement string:
$& - matched text
$_ - original source string
$` - text before match
$' - text after match
${group_name} - text matched by named group
$1, $2 - text matched by numbered group
$$ - the literal "$"
Tuesday, October 2, 2007
Creating a type of Type based on a string
I recently ran into a case where I had a string value like "System.String" and I needed to determine what type this represented, then assign that to a member of type Type.
Type t = Type.GetType("System.String");
Type t = Type.GetType("System.String");
Tuesday, September 25, 2007
Changing to the root directory with FtpWebRequest
Extracted from: http://blogs.msdn.com/mariya/archive/2006/03/06/544523.aspx
Many customers ask us how they can use the CWD command with our FtpWebRequest.
The answer is: you cannot use the command directly, but you can modify the uri parameter to achieve the same result.
Let's say you're using the following format:
String uri = "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl";
FtpWebRequest Request = (FtpWebRequest)WebRequest.Create(uri);
Request.Method = "LIST";
The above example will bring you to your user's directory and list all the contents there. Now let's say you want to go 2 directories backwards and list the contents there (provided your user has permissions to do that). You close the previous FtpWebRequest and issue a new one with this uri
uri = "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl/%2E%2E/%2E%2E";
This is equivalent to logging in with your user's credentials and then using cd ../../
Note: if you try using the ”..” directly without escaping them the uri class will strip them, so "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl/../.." is equivalent to "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl/"
Now let's say you want to go to another user's directory which is one level above the root. If you don't specify a user name and password it's equivalent to logging in as anonymous user. Then you issue a new FtpWebRequest with the following uri
"ftp://myFtpUrl/%2F/anotherUserDir"
This is equivalent to logging in as anonymous and then doing
Cd /
cd anotherUserDirectory
Many customers ask us how they can use the CWD command with our FtpWebRequest.
The answer is: you cannot use the command directly, but you can modify the uri parameter to achieve the same result.
Let's say you're using the following format:
String uri = "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl";
FtpWebRequest Request = (FtpWebRequest)WebRequest.Create(uri);
Request.Method = "LIST";
The above example will bring you to your user's directory and list all the contents there. Now let's say you want to go 2 directories backwards and list the contents there (provided your user has permissions to do that). You close the previous FtpWebRequest and issue a new one with this uri
uri = "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl/%2E%2E/%2E%2E";
This is equivalent to logging in with your user's credentials and then using cd ../../
Note: if you try using the ”..” directly without escaping them the uri class will strip them, so "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl/../.." is equivalent to "ftp://myFtpUserName:myFtpUserPassword@myFtpUrl/"
Now let's say you want to go to another user's directory which is one level above the root. If you don't specify a user name and password it's equivalent to logging in as anonymous user. Then you issue a new FtpWebRequest with the following uri
"ftp://myFtpUrl/%2F/anotherUserDir"
This is equivalent to logging in as anonymous and then doing
Cd /
cd anotherUserDirectory
Monday, September 17, 2007
Binding XML data into a DataList, GridView, etc.
Here is a nice article on how to bind sections of an XML file (or string) into a DataList, GridView, etc. using the .NET 2.0 XmlDataSource. Basically, it is the same as binding a SqlDataSource. It is nice since you can bind a subset of the XML rather than the entire data.
http://aspnet.4guysfromrolla.com/articles/061307-1.aspx
http://aspnet.4guysfromrolla.com/articles/061307-1.aspx
Saturday, August 25, 2007
'asp' is an unrecognized tag prefix or device filter
I'm using Visual Studio 2005 with SP 1. Recently the IDE started showing errors for my asp tags:
'asp' is an unrecognized tag prefix or device filter
There were a lot of online reports that this was a reflection of Master Pages. For me, I was not using Master Pages. My fix was to:
'asp' is an unrecognized tag prefix or device filter
There were a lot of online reports that this was a reflection of Master Pages. For me, I was not using Master Pages. My fix was to:
- Close all VS instances
- Delete folder contents at "C:\Documents and Settings\[Username]\Application Data\Microsoft\VisualStudio\8.0\ReflectedSchemas"
- Restart VS (it will recreate schemas)
Friday, August 24, 2007
Loading PowerShell scripts at startup
If you want to execute a lot of custom scripts/functions when PowerShell starts up, you can either put them all in your startup profile, or use the method below.
Assuming you have a startup profile named Microsoft.PowerShell_Profile.ps1 in:
%UserProfile%\\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile
Create a subdirectory called something like Includes and place all your custom script files in this directory. Finally add the following code into the startup profile:
foreach ($f in get-childitem $(join-path $(split-path $profile -Parent) "Includes"))
{
. $f.fullname
}
Now, each time PowerShell is started, it will automatically execute all your customer shell scripts/functions.
Assuming you have a startup profile named Microsoft.PowerShell_Profile.ps1 in:
%UserProfile%\\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile
Create a subdirectory called something like Includes and place all your custom script files in this directory. Finally add the following code into the startup profile:
foreach ($f in get-childitem $(join-path $(split-path $profile -Parent) "Includes"))
{
. $f.fullname
}
Now, each time PowerShell is started, it will automatically execute all your customer shell scripts/functions.
Powershell Profiles
Extracted from: http://msdn2.microsoft.com/en-us/library/bb613488.aspx
When you add aliases, functions, and variables to Windows PowerShell, you are actually adding them only to the current Windows PowerShell session. If you exit the session or close Windows PowerShell, the changes are lost.
To retain these changes, you can create a Windows PowerShell profile and add the aliases, functions, and variables to the profiles. The profile is loaded every time that Windows PowerShell starts.
To load a profile, your Windows PowerShell execution policy must permit you to load configuration files. If it does not, the attempt to load the profile fails and Windows PowerShell displays an error message.
Understanding the Profiles
You can have four different profiles in Windows PowerShell. The profiles are listed in load order. The most specific profiles have precedence over less specific profiles where they apply.
%windir%\system32\WindowsPowerShell\v1.0\profile.ps1
This profile applies to all users and all shells.
%windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1
This profile applies to all users, but only to the Microsoft.PowerShell shell.
%UserProfile%\My Documents\WindowsPowerShell\profile.ps1
This profile applies only to the current user, but affects all shells.
%UserProfile%\\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
This profile applies only to the current user and the Microsoft.PowerShell shell.
Creating a Profile
When you create or import variables, aliases, or functions, or add a Windows PowerShell snap-in, these elements are added only to the current console. If you exit the session or close the window, they are gone.
To save the variables, aliases, functions, and commands that you use routinely, and make them available in every Windows PowerShell console, add them to your Windows PowerShell profile.
You can also create, share, and distribute profiles to enforce a consistent view of Windows PowerShell in a larger enterprise.
Windows PowerShell profiles are not created automatically. To create a profile, create a text file with the specified name in the specified location. Typically, you will use the user-specific, shell-specific profile, known as the Windows PowerShell user profile. The location of this profile is stored in the $profile variable.
To display the path to the Windows PowerShell profile, type:
$profile
To determine whether a Windows PowerShell profile has been created on the system, type:
test-path $profile
If the profile exists, the response is True; otherwise, it is False.
To create a Windows PowerShell profile file, type:
new-item -path $profile -itemtype file -force
To open the profile in Notepad, type:
notepad $profile
To create one of the other profiles, such as the profile that applies to all users and all shells, type:
new-item -path C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 -itemtype file -force
The profile is effective only when the file is located exactly in the path and with the file name that is stored in the $profile variable. Therefore, if you create a profile in Notepad and then save it, or if you copy a profile to your system, be sure to save the file in the path and with the file name specified in the $profile variable.
If you create a profile in Notepad, enclose the file name in quotation marks to preserve the PS1 file name extension. For example:
"Microsoft.PowerShell_profile.ps1"
Without the quotation marks, Notepad appends the .txt file name extension to the file, and Windows PowerShell will not recognize it.
Use the profile to store the aliases, functions, and variables that you use routinely. One very helpful opens your user profile in your favorite text editor. For example, the following command creates a function called pro that opens the user profile in Notepad.
function pro { notepad $profile }
A well-designed profile can make it even easier to use Windows PowerShell and to administer your system.
When you add aliases, functions, and variables to Windows PowerShell, you are actually adding them only to the current Windows PowerShell session. If you exit the session or close Windows PowerShell, the changes are lost.
To retain these changes, you can create a Windows PowerShell profile and add the aliases, functions, and variables to the profiles. The profile is loaded every time that Windows PowerShell starts.
To load a profile, your Windows PowerShell execution policy must permit you to load configuration files. If it does not, the attempt to load the profile fails and Windows PowerShell displays an error message.
Understanding the Profiles
You can have four different profiles in Windows PowerShell. The profiles are listed in load order. The most specific profiles have precedence over less specific profiles where they apply.
%windir%\system32\WindowsPowerShell\v1.0\profile.ps1
This profile applies to all users and all shells.
%windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1
This profile applies to all users, but only to the Microsoft.PowerShell shell.
%UserProfile%\My Documents\WindowsPowerShell\profile.ps1
This profile applies only to the current user, but affects all shells.
%UserProfile%\\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
This profile applies only to the current user and the Microsoft.PowerShell shell.
Creating a Profile
When you create or import variables, aliases, or functions, or add a Windows PowerShell snap-in, these elements are added only to the current console. If you exit the session or close the window, they are gone.
To save the variables, aliases, functions, and commands that you use routinely, and make them available in every Windows PowerShell console, add them to your Windows PowerShell profile.
You can also create, share, and distribute profiles to enforce a consistent view of Windows PowerShell in a larger enterprise.
Windows PowerShell profiles are not created automatically. To create a profile, create a text file with the specified name in the specified location. Typically, you will use the user-specific, shell-specific profile, known as the Windows PowerShell user profile. The location of this profile is stored in the $profile variable.
To display the path to the Windows PowerShell profile, type:
$profile
To determine whether a Windows PowerShell profile has been created on the system, type:
test-path $profile
If the profile exists, the response is True; otherwise, it is False.
To create a Windows PowerShell profile file, type:
new-item -path $profile -itemtype file -force
To open the profile in Notepad, type:
notepad $profile
To create one of the other profiles, such as the profile that applies to all users and all shells, type:
new-item -path C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 -itemtype file -force
The profile is effective only when the file is located exactly in the path and with the file name that is stored in the $profile variable. Therefore, if you create a profile in Notepad and then save it, or if you copy a profile to your system, be sure to save the file in the path and with the file name specified in the $profile variable.
If you create a profile in Notepad, enclose the file name in quotation marks to preserve the PS1 file name extension. For example:
"Microsoft.PowerShell_profile.ps1"
Without the quotation marks, Notepad appends the .txt file name extension to the file, and Windows PowerShell will not recognize it.
Use the profile to store the aliases, functions, and variables that you use routinely. One very helpful opens your user profile in your favorite text editor. For example, the following command creates a function called pro that opens the user profile in Notepad.
function pro { notepad $profile }
A well-designed profile can make it even easier to use Windows PowerShell and to administer your system.
Monday, August 13, 2007
PowerShell Prompt Utility
This utility allows you to launch a Windows PowerShell command-prompt directly from Windows Explorer via a right-click. Extract, right-click and select "Install".
Download Here
Download Here
Saturday, August 11, 2007
UPS development tracking tools
You can integrate UPS (United Parcel Service) package tracking into your application using the tools found at UPS below. This supports both an HTTP and XML interface. You will need to sign up and get a UPS license to track packages, which is free.
http://www.ups.com/content/us/en/tracking/tools/index.html
http://www.ups.com/content/us/en/tracking/tools/index.html
Monday, August 6, 2007
Set EXECUTE on SQL stored procedures
If you have created and restored a SQL database, the stored procedures may need to have EXECUTE privilege set on them. If there are lots of these procedures, it can be tedious to do it by hand. The query below will output the T-SQL command(s) to set EXECUTE on each procedure. You can then copy/paste the result and execute it.
USE [DbNameHere]
SELECT 'GRANT EXECUTE ON ' + name + ' TO [NT AUTHORITY\NETWORK SERVICE]'
FROM sysobjects
WHERE type = 'P' AND name like 'sp_%'
Friday, August 3, 2007
Column guides in Visual Studio
Here are instructions for adding visual column indicators to the Visual Studio editor. This helps when trying to keep your code lines within a certain character limit.
Make the following new registry string values.
For Visual Studio 2003:
Location: [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\Text Editor]
String Value: Guides=RGB(128,0,0) 80, 120
For Visual Studio 2005:
Location: [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Text Editor]
String Value: Guides=RGB(128,0,0) 80, 120
This sets column markers at 80 and 120 characters respectively.
Make the following new registry string values.
For Visual Studio 2003:
Location: [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\Text Editor]
String Value: Guides=RGB(128,0,0) 80, 120
For Visual Studio 2005:
Location: [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Text Editor]
String Value: Guides=RGB(128,0,0) 80, 120
This sets column markers at 80 and 120 characters respectively.
Wednesday, August 1, 2007
C# Generics (.NET 2.0)
Here is an MSDN article on using .NET 2.0 Generics. It's one of the better ones I have found.
Download Here
Download Here
Virtual CD Driver for XP
This utility allows you to create a virtual CD for Windows XP. Once created, you can mount ISO files and view them just like it was a directory structure.
Download Here
Download Here
DOS Prompt Utility for Visual Studio
This utility allows you to launch a Visual Studio command-prompt directly from Windows Explorer via a right-click. Extract your version (VS 2003, VS 2005), right-click and select "Install".
Download Here
Download Here
Book Recommendations
Here are some great books, in my opinion, on software development, design, C#, etc. Click to view/buy on Amazon.
Agile Estimating and Planning, Prentice Hall, ISBN #0131479415
Agile Principles, Patterns, and Practices, Prentice Hall, ISBN #0131857258
Learning jQuery 1.4, PACKT, ISBN #978-1849510042
CSS Mastery, 2nd Edition, Advanced Web Standards Solutions, friends of ED, ISBN #1430223979
Windows PowerShell In Action, Manning Publications, ISBN #1932394907
Agile Estimating and Planning, Prentice Hall, ISBN #0131479415
Agile Principles, Patterns, and Practices, Prentice Hall, ISBN #0131857258
Learning jQuery 1.4, PACKT, ISBN #978-1849510042
CSS Mastery, 2nd Edition, Advanced Web Standards Solutions, friends of ED, ISBN #1430223979
Windows PowerShell In Action, Manning Publications, ISBN #1932394907
Subscribe to:
Posts (Atom)
Can't RDP? How to enable / disable virtual machine firewall for Azure VM
Oh no! I accidentally blocked the RDP port on an Azure virtual machine which resulted in not being able to log into the VM anymore. I did ...
-
Oh no! I accidentally blocked the RDP port on an Azure virtual machine which resulted in not being able to log into the VM anymore. I did ...
-
Here is a full test program that demonstrates how to use SharpZipLib to zip an XElement into a byte array. This allows you to transfer larg...