StgOpenStorageEx .Net C#

September 19, 2010 at 12:37 PMRampidByter

Sometimes I think my attention span is consistent as a cat faced with a dot or red light on the carpet. Luckily it often leads to some very cool rabbit holes. I ended up digging into file properties on a whole new level, which are a lot more complicated than I once thought. Long story short I ended up meeting the StgOpenStorageEx function, the IPropertySetStorage, and of course the IPropertyStorage interfaces.

I spent two days of exhausting search referencing through MSDN on structs, enums, and function declarations. Countless C++, .Net code forums, and even a Delphi coding sites looking for working examples of reading file properties. Most were filled with examples that didn’t work, or were postings of unsolved errors. I ran into many errors ranging from “E_INVALIDARG” of the IPropertyStorage.ReadMultiple function to the time spent building the classes required. Turns out PInvoke.net and most other sites all have invalid function declarations in one way or another.

All the trouble could have been saved by simply using the “Microsoft.VisualStudio.OLE.Interop” assembly to get access to the fully flushed out interfaces and required structs. Short of declaring the StgOpenStorageEx extern function the Interop assembly contains all the other required classes. The assembly can be installed with the Visual Studio SDK (2010 in my case) installer located on the Microsoft download page. I wish I had known that two days ago.

Posted in: .Net | Programming

Tags:

Microsoft Pivot Blog Viewer

July 26, 2010 at 7:59 AMRampidByter

Ok, I built something I am excited about. The one biggest gripe I’ve had with blogs is that it’s often hard to sort and filter the posts to find the posts I’m most interested in. In comes Microsoft Pivot. Microsoft Pivot allows for viewing data in an intuitive filterable manner in a completely visual context. Incredibly cool for filtering images, magazines, or even the magic the gathering card collection. Take that single column blog lists!

My idea last night is to view blogs through Pivot. I set about programming the cXML schema into a series of .Net classes, and then built an input mechanism to build a static cXML file with my blogs postings. It’s still in the early phase of just the roughest information, mainly blog title and descriptions, but given another day of polishing will have additional meta data with appropriate blog links. I also realize how terrible my categories are since the Pivot category filtering is very limited with my junk data input.

Below is a screen shot of the very rough data output I created with cXML for viewing in Microsoft Pivot. Now that I have my framework together I can expand the idea to anything with categories.

PivotBlog

I will keep the cXML path displayed in the Pivot screenshot so if you’re interested you can also view the generated blog Pivot output as it goes through the transition to getting cleaned up totally.

Posted in: .Net | Microsoft | Programming

Tags:

VB.Net inline XML loop

July 20, 2010 at 9:43 PMRampidByter

Coming from a C# background I was a little jealous of VB literals (still hate VB.) Recently I was flung into the VB.Net world on a new project, and my only consolation was finally being able to work with VB literals first hand. The first thing I needed to do was iterate a collection of objects to custom build an XML message. I did a little Google, and Bing action to no real results on looping a collection within XML literals. Eventually I found the solution as XML literals do not directly support loops as we know it. Fortunately that is where LINQ steps up to the plate:

 1: Dim xml = <Processes>
 2:  <%= From process in Processes 
 3:  Select <Process><%= process.Name %></Process>
 4:  %>
 5:  </Processes>

In this example I’ve created an XElement variable called “xml” that contains the literal XML. Using a LINQ query within the “Processes” element the select query will iterate through the items in the processes collection object. Each item will output a process element that will be included within the processes element.

Posted in: .Net | Programming

Tags:

.Net Extension Methods – Extending ViewState With Generics

May 15, 2010 at 4:35 PMRampidByter

I may be a little late to the party on mentioning how much extension methods have made my life easier. Extension methods tend to fill that gap between wanting to add an extra little tweak to an existing class without actually having to implement a customized inherited version. Previously whenever you wanted to use one extra tweak or feature you’d be responsible for making sure to replace all instances of the inherited class with your new version. That gets into supporting the new class when all you wanted to do was change or add one thing to an existing class!

In my case I just really wanted to stop having to check whether a ViewState value was null before trying to unbox the value into whatever value type or class I thought I stored in that key’s value field. In my case I really wanted to add generic typing support to the ViewState property of the page with as little work as possible. That is exactly where Extension methods come to the rescue.

For example normally one would see the following code to access a ViewState property:

 1: private int GetGroupId()
 2: {
 3:  int groupId = -1;
 4:  
 5:  if(ViewState["CurrentGroupId"] != null)
 6:  {
 7:  groupId = (int)ViewState["CurrentGroupId"];
 8:  }
 9:  
 10:  return groupId;
 11: }

 

Ideally I would like to do the following:

 1: private int GetGroupId()
 2: {
 3:  return ViewState.Get<int>("CurrentGroupId", delegate { return -1; });
 4: }

 

To do this I’d use a .Net extension method to extend the ViewState property through it’s StateBag class. Below you’ll find the ViewStateHelper class with all the required code to extend the StateBag class, thereby extending the ViewState property, and adding support for generic Get/Set functions. In order to use it just add the namespace where the static class is contained to the “usings” on the code-behind file of the page needing the ViewState extension support.

 1:  public static class ViewStateHelper
 2:  {
 3:  /// <summary>
 4:  /// Returns an object from view state
 5:  /// </summary>
 6:  /// <typeparam name="T">Type of object</typeparam>
 7:  /// <param name="key">View state key of object</param>
 8:  /// <param name="delegateDefault">If view state is empty, a delegate to return a value to put in view state.</param>
 9:  /// <returns></returns>
 10:  public static T Get<T>(this StateBag viewState, string key, DefaultMethod<T> delegateDefault)
 11:  {
 12:  T viewStateValue;
 13: 
 14:  if (viewState != null &&
 15:  viewState[key] != null &&
 16:  viewState[key].GetType() == typeof(T))
 17:  {
 18:  viewStateValue = (T)viewState[key];
 19:  }
 20:  else
 21:  {
 22:  viewStateValue = delegateDefault();
 23:  viewState.Set<T>(key, viewStateValue);
 24:  }
 25:  
 26:  return viewStateValue;
 27:  }
 28:  
 29:  /// <summary>
 30:  /// Put an object in view state
 31:  /// </summary>
 32:  /// <typeparam name="T">Type of object to put in view state</typeparam>
 33:  /// <param name="key">Key of object to put in view state</param>
 34:  /// <param name="value">Object to put in view state</param>
 35:  public static void Set<T>(this StateBag viewState, string key, T value)
 36:  {
 37:  if (value != null)
 38:  viewState[key] = value;
 39:  else
 40:  viewState.Remove(key);
 41:  } 
 42:  }

Posted in: .Net | ASP.Net | Programming

Tags:

DataGridView Drag and Drop with Multiple Files

January 14, 2010 at 12:44 AMRampidByter

I was working on a project tonight and I noticed something kind of odd. There are a ton of references out there for how to handle the DragDrop event with a single file, but I wasn’t able to find really anything about handling multiple files. Needless to say I figured I’d make a post to remedy this problem.

First thing to note is to select the DataGridView in the designer and from the properties window set “Allow Drop” to “True" to enable the events. Second is to add an event handler to the DataGridView DragEnter event. Within the event simply set e.Effect to one of the desired DragDropEffects enumeration values as such:

private void dgvImageFiles_DragEnter(object sender, DragEventArgs e)
{
 e.Effect = DragDropEffects.Copy;
}

The next step is to simply add an event handler for the DragDrop event and use e.Data.GetData(“FileDrop”) to get a string array containing the full file paths to each file dropped into the DataGridView control. That was at least my desire when building this code, but you could just as easily handle any of the other data format values available from e.Data.GetFormats() function. Below is the DragDrop event I’ve used to get the files dropped into the DataGridView control:

 private void dgvImageFiles_DragDrop(object sender, DragEventArgs e)
 { 
 if (e.Data.GetDataPresent("FileDrop"))
 {
 string[] files = (e.Data.GetData("FileDrop") as string[]);
 
 foreach (string file in files)
 {
 . . . 
 }
 }
 }

That is how to handle drag and drop with the DataGridView with multiple files. Easy enough eh? Well then back to programming I go.

Posted in: .Net | Programming

Tags:

WCF – HttpGetEnabled property of ServiceMetadataBehavior Error

October 16, 2009 at 3:08 PMRampidByter

Added SSL recently to our production WCF service site. The big change happened when trying to setup a customer feed to begin testing implementations against the fixed service location. After setting the site to require SSL a particular friendly yellow-screen-of-death appeared with the following message The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the HttpGetUrl property is a relative address, but there is no http base address.  Either supply an http base address or set HttpGetUrl to an absolute address.”

The fix is to change the httpGetEnabled=”true” to httpsGetEnabled=”true” under serviceMetadata tag for the defined service behavior settings. A simple little s character cost an hour of time in configuration to find. There was another one similar when changing the IMetadataExchange endpoint to use mexHttpsBinding instead of mexHttpBinding. That was another topic all together but very related as far as the fix. Below you’ll find a snippet of the configuration section with https changes.

 1:  <behaviors>
 2:  <serviceBehaviors>
 3:  <behavior name="Services.ServiceBehavior">
 4:  <serviceCredentials>
 5:  <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Services.Validators.UserValidator, Services"/>
 6:  </serviceCredentials>
 7:  <serviceMetadata httpsGetEnabled="true" />
 8:  <serviceDebug includeExceptionDetailInFaults="false" />
 9:  </behavior>
 10:  </serviceBehaviors>
 11:  </behaviors>

Posted in: .Net | Programming | WCF

Tags:

.Net 4.0 and IIS 7 Application Pool Problem

September 28, 2009 at 9:42 PMRampidByter

Ok, I admit it. I am one of those people who likes new technologies. I also am ‘that guy’ who installs a beta framework on a production web server just so I can host a new website using the bleeding edge technology/framework. They don’t call it bleeding edge for nothing because sometimes it can just plain hurt after you install said new technology and the new technology takes down the existing system.

That is exactly what happened when I installed .Net 4 on my web server. The next thing i know after the installation and planned restart all of my websites were redirecting to the 404 website not found page. Fantastic, it’s 1am, I've just installed a beta framework, and all of my websites are effectively offline. Well that’s what i get, but at least it’s my personal server instead of a corporate server I work on. I know better than that by now, and if didn’t I wouldn’t have a job. Not saying I’ve not been guilty of taking down a web server before.

Anyway, the first thing that happened as I said was the 404 pages. From the ten website impacted only one gave the yellow-screen of death. Thankfully I was able to just simply set the custom error configuration to off so I could read the error. Sure enough it’s an error related to running a website in an application pool using a framework not supported by the configuration settings. After checking the application pools every single last one of them were set to .Net 4.0 integrated instead of the respective .Net 2.0 integrated/classic set on the individual sites. A few drop-down lists later my websites were all back up and functioning, but I was left with the “what else is impacted” feeling after the installation. You’d think after four framework releases the installer and framework configuration installation would have been set better than to default all my application pools to use .Net 4.0. It’s not like it’s the only option available.

Again to recap the .Net 4.0 Beta installer will change your IIS 7 (i assume IIS 5/6) website applications pools to use .Net 4.0 instead of your predefined settings. Just change them back and everything starts functioning again. Hopefully this will be the last “oh what have I done!” I run into after installing the beta framework. Fingers crossed!

Posted in: .Net | Hardware | Microsoft

Tags:

Windows Remote Desktop Port Number Changer

December 28, 2008 at 10:44 PMRampidByter

I was setting up my new laptop this morning and I then started to get into configuring port forwarding on my router. Because this computer is becoming another ad-hoc development machine i decided to add it to the list of PC's i have that are able to be used remotely. To do this i needed to change the default port from 3389 to a custom port number. I again went through the hassle of looking on-line for a site that had the registry path to the terminal services RDP port number setting. It was at this point that either my lazy bone or my uber programming sense kicked in and i made a quick utility to use whenever i need to set the port number again. Thus saving me the hassle of again looking up the registry path, and then skimming through the registry hive looking for the setting using RegEdit.

Here is the code to a quick Console application program i wrote that can be used through command line argument or via standard command line interface.

 1: using System; 
 2: using Microsoft.Win32; 
 3:   
 4: namespace RemotePortChanger 
 5: { 
 6:  class Program 
 7:  { 
 8:  static void Main(string[] args) 
 9:  { 
 10:  int portNumber = 3389; 
 11:   
 12:  try 
 13:  { 
 14:  if (args.Length > 0) 
 15:  { 
 16:  int.TryParse(args[0], out portNumber); 
 17:   
 18:  SetPort(portNumber); 
 19:  } 
 20:  else 
 21:  { 
 22:  string input = string.Empty; 
 23:   
 24:  Console.WriteLine("Remote Desktop Port: " + GetPort()); 
 25:  Console.Write("Enter the new port number: "); 
 26: 
 27:  input = Console.ReadLine(); 
 28:   
 29:  int.TryParse(input, out portNumber); 
 30:   
 31:  SetPort(portNumber); 
 32:   
 33:  Console.WriteLine("Port is now " + GetPort() + " press any key to exit."); 
 34:  Console.Read(); 
 35:  } 
 36:  } 
 37:  catch (Exception ex) 
 38:  { 
 39:  Console.WriteLine("Error has occured - " + ex.Message); 
 40:  } 
 41:  } 
 42:   
 43:  private static void SetPort(object portNumber) 
 44:  { 
 45:  RegistryKey key; 
 46:   
 47:  key = Registry.LocalMachine; 
 48:  key = key.OpenSubKey(@"System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp", true); 
 49:  key.SetValue("PortNumber", portNumber); 
 50:  key.Close(); 
 51:  } 
 52:   
 53:  private static int GetPort() 
 54:  { 
 55:  RegistryKey key; 
 56:  int portNumber = 0; 
 57:   
 58:  key = Registry.LocalMachine; 
 59:  key = key.OpenSubKey(@"System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"); 
 60:  portNumber = Convert.ToInt32(key.GetValue("PortNumber")); 
 61:   
 62:  return portNumber; 
 63:  } 
 64:  } 
 65: } 


Posted in: .Net | Microsoft | Programming

Tags:

Auto-Updater

March 26, 2008 at 6:48 AMRampidByter

After the last few releases of applications I’ve been creating for my client it became apparent that we were in need of a more automated process that could guarantee that each employee using the software was aware of, and was made to upgrade to the latest version. This came after a relatively small change to the program to pull more data from a database than trying to dynamically determine the information from disconnected data. The systems around here are a bit on the rustic side of the technology spectrum.

 

Anyway, we’re using Framework 1.1 and desktop deployments are not as user friendly as the ClickOnce of Framework 2.0. There are still the manual processes, and the limitations of not having proper system/network access being a lowly consultant. So, I decided I would write an auto-updating plug-in for the applications, but first I’d check to see what others have done in order to save myself time.

 

That’s when I came across an article by Peter A. Bromber, Ph.D., that addressed building a Framework 1.1 Automatic Application MSI Updater. Pretty swanky, so I decided I’d take a look at his code as obviously he’s run into problems similar to my own. After digesting everything that he had to offer my mouth was left with an unsatisfying flavor of, well, I could do better to say for short.

 

Article for reference: http://www.eggheadcafe.com/articles/20060213.asp

 

Seeing that I could not use a webservice, since I’m not allowed to access the main servers, I was left with a less dynamic alternative. I would just have to use the App.Config file to point my application to an Access database, don’t ask. The access database I’d model similar to Dr. Brombers, but with better column names.

 

I then crafted my own implementation of his code, I noticed early on his recursive lookup for the assembly version was pointless, and also decided to create a typed dataset to return my data values. So I present to you my own implementation, in the works, of the Framework 1.1 Auto-Updater. Of course it’s still in the works as I’m not particularly fond of the fact that while the new installer is running, if you’re installing into the same file directory the running application can not complete until the old application is closed. You are forced to hit the ‘continue’ button twice in order to force the installer to overwrite the running application who spawned the installer via a new process. Anyway, here is my updated code:

 

using System;
using System.Configuration;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Forms;
using ClientName;

namespace ClientName
{

///<summary>
///
///</summary>
publicclass AutoUpdater
{
privatestatic OleDbConnection connUpgrade;

///<summary>
/// Opens the Upgrade databases OLE DB connection.
///</summary>
privatestaticvoid OpenDbConnection()
{
string connString = string.Empty;

try
{
connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ConfigurationSettings.AppSettings.Get("UpgradeDbPath");
connUpgrade = new OleDbConnection(connString);
connUpgrade.Open();
}
catch(Exception err)
{
CloseDbConnection();
}
}


///<summary>
/// Closes the Upgrade databases OLE DB connection.
///</summary>
privatestaticvoid CloseDbConnection()
{
if(connUpgrade != null)
{
if(connUpgrade.State != ConnectionState.Closed)
{
connUpgrade.Close();
connUpgrade.Dispose();
connUpgrade = null;
}
}
}

///<summary>
///
///</summary>
///<returns></returns>
publicstaticbool CheckForUpdate()
{
bool result = false;
string appName = string.Empty;
string lastVersion = string.Empty;
string currentVersion = string.Empty;
string appExeName = string.Empty;
UpdateDataset.AppVersionsRow appRow = null;

try
{
// Get the current assemblies Product Name
appName = Assembly.GetEntryAssembly().GetName().Name;
appRow = GetAppVersionInfo(appName);

if(appRow != null)
{
lastVersion = Application.ProductVersion;

if
(appRow.CurrentVersion != lastVersion)
{
UpdateForm frmUpdate = new UpdateForm();
frmUpdate.BringToFront();
frmUpdate.StartPosition = FormStartPosition.CenterScreen;
DialogResult dlgResult = frmUpdate.ShowDialog();

if (frmUpdate.UserAccept == true)
{
Process proc = new Process();
proc.StartInfo.FileName = appRow.AppExeName;
proc.StartInfo.WorkingDirectory = appRow.InstallerPath;
proc.Start();
proc.WaitForExit();
Process.Start(Application.ExecutablePath);
Environment.Exit(0);
}
elseif (dlgResult == DialogResult.Cancel)
{
result = false;
}
}
}
}
catch(Exception err)
{
Environment.Exit(0);
}

return result;
}

///<summary>
/// Gets the Application Version record for the supplied
/// application product name.
///</summary>
///<param name="appName"></param>
///<returns></returns>
privatestatic UpdateDataset.AppVersionsRow GetAppVersionInfo(string appName)
{
string sqlSelect = string.Empty;
UpdateDataset dsUpdate = null;
OleDbDataAdapter adapter = null;
OleDbParameter param = null;
UpdateDataset.AppVersionsRow appRow = null;

try
{
dsUpdate = new UpdateDataset();

sqlSelect = @"SELECT AppName, AppExeName, InstallerPath, CurrentVersion FROM AppVersions WHERE AppName = @appName";

OpenDbConnection();

adapter = new OleDbDataAdapter(sqlSelect, connUpgrade);

param = new OleDbParameter("@appName", OleDbType.VarChar);
param.Value = appName;

adapter.SelectCommand.Parameters.Add(param);
adapter.Fill(dsUpdate.AppVersions);

CloseDbConnection();

appRow = dsUpdate.AppVersions.FindByAppName(appName);
}
catch(Exception err)
{
string message = err.Message;
}
finally
{
CloseDbConnection();
}

return appRow;
}
}
}

Posted in: .Net

Tags: