Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Adding / removing shortcut for application in Today's screen using C#

28 views
Skip to first unread message

Harsh Trivedi

unread,
Nov 12, 2009, 11:11:49 AM11/12/09
to
I am developing application in Windows mobile 6.0, using C# and .NET
CF 2.0.

I want to create a shortcut icon on Today's screen, and want to remove
it using C#... does anyone knows how to achieve it? I have seen for
Startup or Start menu, which is ok, but not sure about on Today's
screen.

Thanks

Christian Resma Helle

unread,
Nov 12, 2009, 4:13:13 PM11/12/09
to
A few years back I wanted to do the same. Here's some old code I dug up.
Write back if it doesn't work, I think I have messed up the version control
I used back then. But I'm sure we deployed this on an application running
in a production environment, I'm just not sure if its this exact version
of the code.


============
== C# Code
============


/// <summary>
/// Enable and Disable Today Screen Items
/// </summary>
public class Today
{
/// <summary>
/// Checks the RegistryImpl if the Today Screen item exists
/// </summary>
/// <param name="item">Item Name</param>
/// <returns>returns TRUE if the item exists, otherwise FALSE</returns>
public static bool DoesItemExist(string item)
{
uint key = 0;
string subkey = string.Format(@"SOFTWARE\Microsoft\Today\Items\{0}",
item);
if (RegistryImpl.RegOpenKeyEx((uint)RegistryImpl.RootKey.HKEY_LOCAL_MACHINE,
subkey, 0, 0, ref key) == 0)
{
RegistryImpl.RegCloseKey(key);
return true;
}
else return false;
}

/// <summary>
/// Checks the registry if the item is enabled
/// </summary>
/// <param name="item">Item Name</param>
/// <returns>returns TRUE if the item exists and is enabled, otherwise
FALSE</returns>
public static bool IsItemEnabled(string item)
{
uint key = 0;
string subkey = string.Format(@"SOFTWARE\Microsoft\Today\Items\{0}",
item);
if (RegistryImpl.RegOpenKeyEx((uint)RegistryImpl.RootKey.HKEY_LOCAL_MACHINE,
subkey, 0, 0, ref key) == 0)
{
int type = 0;
int size = 0;
byte[] data = null;
if (RegistryImpl.RegQueryValueEx(key, subkey, 0, ref type,
data, ref size) == 0)
{
data = new byte[size];
if (RegistryImpl.RegQueryValueEx(key, subkey, 0, ref
type, data, ref size) == 0)
{
if (type != RegistryImpl.REG_DWORD)
return false;
}
else return false;

return ((uint)BitConverter.ToInt32(data, 0) == 1) ? true
: false;
}
else return false;
}
else return false;
}

/// <summary>
/// Causes the Today screen to re-read from the RegistryImpl
/// </summary>
public static void RefreshTodayScreen()
{
Window.SendMessage("DesktopWindowExplorer", "Desktop",
WindowMessages.WM_WININICHANGE, 0x000000F2,
0);
}

/// <summary>
/// Enable the Today Screen item
/// </summary>
/// <param name="item">Item Name</param>
/// <returns>returns TRUE if successful, otherwise FALSE</returns>
public static bool EnableTodayScreen(string item)
{
bool status = false;
int err = 0;

uint key = 0;
string subkey = string.Format(@"SOFTWARE\Microsoft\Today\Items\{0}",
item);
if (RegistryImpl.RegOpenKeyEx((uint)RegistryImpl.RootKey.HKEY_LOCAL_MACHINE,
subkey, 0, 0, ref key) == 0)
{
byte[] value = BitConverter.GetBytes(1);
subkey = string.Format(@"{0}\Enabled", subkey);

err = RegistryImpl.RegSetValueEx(key, subkey, 0, RegistryImpl.REG_DWORD,
value, value.Length);
status = (err == 0) ? true : false;

err = RegistryImpl.RegCloseKey(key);
status = (err == 0) ? true : false;

status = Window.SendMessage("DesktopWindowExplorer", "Desktop",
WindowMessages.WM_WININICHANGE,
0x000000F2, 0);

return status;
}
else return false;
}

/// <summary>
/// Disables the Today Screen item
/// </summary>
/// <param name="item">Item Name</param>
/// <returns>returns TRUE if successful, otherwise FALSE</returns>
public static bool DisableTodayScreen(string item)
{
bool status = false;
int err = 0;

uint key = 0;
string subkey = string.Format(@"SOFTWARE\Microsoft\Today\Items\{0}",
item);
if (RegistryImpl.RegOpenKeyEx((uint)RegistryImpl.RootKey.HKEY_LOCAL_MACHINE,
subkey, 0, 0, ref key) == 0)
{
byte[] value = BitConverter.GetBytes(0);
subkey = string.Format(@"{0}\Enabled", subkey);

err = RegistryImpl.RegSetValueEx(key, subkey, 0, RegistryImpl.REG_DWORD,
value, value.Length);
status = (err == 0) ? true : false;

err = RegistryImpl.RegCloseKey(key);
status = (err == 0) ? true : false;

Window.SendMessage("DesktopWindowExplorer", "Desktop",
WindowMessages.WM_WININICHANGE, 0x000000F2,
0);

return status;
}
else return false;
}
}


/// <summary>
/// Represents a key level node in the Windows registry.
/// This class is a registry encapsulation.
/// </summary>
public sealed class RegistryKey : IDisposable
{
private bool m_bReadOnly = true;
private uint m_uiHKey = 0;
private string m_sName = null;

/// <summary>
/// This method should only be called by the Registry class to set
up the root keys!
/// </summary>
/// <param name="rootKey"></param>
internal RegistryKey(uint rootKey, string rootKeyName)
{
m_uiHKey = RegistryImpl.OpenKey(rootKey, "");
m_bReadOnly = true;
m_sName = rootKeyName;
}

internal RegistryKey(uint rootKey, string rootKeyName, string subkey)
{
RegistryImpl.KeyDisposition disp = 0;
m_uiHKey = RegistryImpl.CreateKey(rootKey, subkey, null, ref
disp);
m_bReadOnly = false;

m_sName = rootKeyName + "\\" + subkey;
}

/// <summary>
/// Closes the key and flushes it to disk if the contents have been
modified.
/// </summary>
~RegistryKey()
{
Dispose();
}

/// <summary>
/// Closes the key and flushes it to disk if the contents have been
modified.
/// </summary>
public void Close()
{
if (m_uiHKey != 0)
{
RegistryImpl.RegCloseKey(m_uiHKey);
m_uiHKey = 0;
}
}

/// <summary>
/// Creates a new subkey or opens an existing subkey. The string
subKey is not case-sensitive.
/// </summary>
/// <param name="subkey">Name or path of subkey to create or open.
</param>
/// <returns>Returns the subkey, or null if the operation failed.</returns>
public RegistryKey CreateSubKey(string subkey)
{
AssertIsOpen();

return new RegistryKey(m_uiHKey, Name, subkey);
}

/// <summary>
/// Deletes the specified subkey. The string subkey is not case-sensitive.
/// </summary>
/// <param name="subkey">Name of the subkey to delete.</param>
/// <param name="throwOnMissing">Indicates whether an exception should
be raised
/// if the specified subkey cannot be found. If this argument is
true and the
/// specified subkey does not exist then an exception is raised.
If this argument
/// is false and the specified subkey does not exist, then no action
is taken
/// </param>
public void DeleteSubKey(string subkey, bool throwOnMissing)
{
AssertIsOpen();

// make sure we are not read only
if (m_bReadOnly)
throw new UnauthorizedAccessException("The subkey cannot
be deleted. The registry key was opened as read only");

// do the check to see if the key actually exists
uint retKey = 0;
int retVal = RegistryImpl.RegOpenKeyEx(m_uiHKey, subkey, 0, 0,
ref retKey);
if (retVal != 0)
{
if (throwOnMissing)
throw new Exception("The subkey " + subkey + " cannot
be deleted because it is missing.");
return;
}

// check and see if the subkey to delete has any subkeys of its
own
char[] chNull = null;
int iNull = 0;
int cSubKey = 1;
RegistryImpl.RegQueryInfoKey(retKey, chNull, ref iNull, 0, ref
cSubKey, ref iNull, ref iNull, ref iNull,
ref iNull, ref iNull, 0, 0);

if (cSubKey != 0)
{
RegistryImpl.RegCloseKey(retKey);
throw new InvalidOperationException("The specified subkey
has child keys");
}

// we are all good, delete the key
RegistryImpl.RegDeleteKey(m_uiHKey, subkey);
}

/// <summary>
/// Deletes the specified subkey. The string subkey is not case-sensitive.
/// </summary>
/// <param name="subkey">Name of the subkey to delete.</param>
public void DeleteSubKey(string subkey)
{
// just call the overloaded function
DeleteSubKey(subkey, false);
}

/// <summary>
/// Deletes a subkey and any child subkeys recursively. The string
subKey is not case-sensitive.
/// </summary>
/// <param name="subkey">Subkey to delete</param>
public void DeleteSubKeyTree(string subkey)
{
AssertIsOpen();

// make sure we are not read only
if (m_bReadOnly)
throw new UnauthorizedAccessException("The subkey cannot
be deleted. The registry key was opened as read only");

// delete the key
RegistryImpl.RegDeleteKey(m_uiHKey, subkey);
}

/// <summary>
/// Deletes the specified value from this key. The string subKey
is not case sensitive.
/// </summary>
/// <param name="val">Name of the value to delete.</param>
/// <param name="throwOnMissing">Indicates whether an exception should
be raised
/// if the specified value cannot be found. If this argument is true
and the specified
/// value does not exist then an exception is raised. If this argument
is false and
/// the specified value does not exist, then no action is taken</param>
public void DeleteValue(string val, bool throwOnMissing)
{
AssertIsOpen();

// make sure we are not read only.
if (m_bReadOnly)
throw new UnauthorizedAccessException("The value cannot be
deleted. The registry key was opened as read only");

if (throwOnMissing)
{
// do the check to see if the key actually exists
int type = 0;
int size = 0;
byte[] data = null;
if (RegistryImpl.RegQueryValueEx(m_uiHKey, val, 0, ref type,
data, ref size) != 0)
throw new Exception("The value " + val + " cannot be
deleted because it is missing.");
}

RegistryImpl.RegDeleteValue(m_uiHKey, val);
}

/// <summary>
/// Deletes the specified value from this key. The string subKey
is not case sensitive.
/// </summary>
/// <param name="val">Name of the value to delete..</param>
public void DeleteValue(string val)
{
// just call the overloaded function
DeleteValue(val, false);
}

/// <summary>
/// Retrieves the count of subkeys at the base level, for the current
key.
/// </summary>
public int SubKeyCount
{
get
{
AssertIsOpen();

int Subkeys = 0;
int nullStuff = 0;
char[] test = null;

// query the registry key for the number of subkeys
int retVal =
RegistryImpl.RegQueryInfoKey(m_uiHKey, test, ref nullStuff,
0, ref Subkeys, ref nullStuff, ref nullStuff,
ref nullStuff, ref nullStuff,
ref nullStuff, 0, 0);

return Subkeys;
}
}

/// <summary>
/// Retrieves an array of strings that contains all the subkey names.
/// </summary>
/// <returns>An array of strings that contains the names of the subkeys
for the current key.</returns>
public string[] GetSubKeyNames()
{
AssertIsOpen();

// create an arraylist to temporarily hold our subkey names
ArrayList subKeyNames = new ArrayList();
int nullStuff = 0;
int iMaxSubKeyLen = 255;
char[] chNull = null;

int iSubKeyLen = 0;
char[] chSubKeyName = new char[iMaxSubKeyLen];
for (int x = 0; x < SubKeyCount; x++)
{
// call RegEnumKeyEx for as many subkeys there are
iSubKeyLen = iMaxSubKeyLen;
RegistryImpl.RegEnumKeyEx(m_uiHKey, x, chSubKeyName, ref
iSubKeyLen, 0, chNull, ref nullStuff, 0);

subKeyNames.Add(new string(chSubKeyName, 0, iSubKeyLen));
}

// return the array as a string Array
return (string[])subKeyNames.ToArray(typeof(string));
}

/// <summary>
/// Retrieves the count of values in the key.
/// </summary>
public int ValueCount
{
get
{
AssertIsOpen();

int icValueKeys = 0;
int nullStuff = 0;
char[] test = null;

// query the registry for the number of values in the current
key.
int retVal =
RegistryImpl.RegQueryInfoKey(m_uiHKey, test, ref nullStuff,
0, ref nullStuff, ref nullStuff, ref nullStuff,
ref icValueKeys, ref nullStuff,
ref nullStuff, 0, 0);

return icValueKeys;
}
}

/// <summary>
/// Retrieves an array of strings that contains all the value names
associated with this key.
/// </summary>
/// <returns>An array of strings that contains the value names for
the current key.</returns>
public string[] GetValueNames()
{
AssertIsOpen();

// array list to temporarily hold the names of the values
ArrayList valueNames = new ArrayList();
int iMaxValueNameLen = 255;
byte[] byData = null;
int iDataLen = 0;
int iType = 0;

int iValueNameLen = 0;
char[] chValueName = new char[iMaxValueNameLen];
for (int x = 0; x < ValueCount; x++)
{
// call RegEnumKeyEx for all the values in the
iValueNameLen = iMaxValueNameLen;
RegistryImpl.RegEnumValue(m_uiHKey, x, chValueName, ref iValueNameLen,
0, ref iType, ref byData, ref iDataLen);

valueNames.Add(new string(chValueName, 0, iValueNameLen));
}

return (string[])valueNames.ToArray(typeof(string));
}

/// <summary>
/// Retrieves the specified value, or the default value you provide
if the specified value is not found.
/// </summary>
/// <param name="val">Name of the value to retrieve.</param>
/// <param name="initialValue">Value to return if name does not exist.</param>
/// <returns>The data associated with name, or defaultValue if name
is not found.</returns>
public object GetValue(string val, object initialValue)
{
AssertIsOpen();

int iType = 0;
int icData = 0;
byte[] byData = null;

// read in the value information, if no value exists, just return
the initial value specified
if (RegistryImpl.RegQueryValueEx(m_uiHKey, val, 0, ref iType,
byData, ref icData) != 0)
return initialValue;

byData = new byte[icData];
if (RegistryImpl.RegQueryValueEx(m_uiHKey, val, 0, ref iType,
byData, ref icData) != 0)
return initialValue;

// Switch the type we have, and convert to the proper type
switch (iType)
{
case RegistryImpl.REG_BINARY:
return byData;

case RegistryImpl.REG_DWORD:
return BitConverter.ToInt32(byData, 0);

case RegistryImpl.REG_SZ:
return UnicodeEncoding.Unicode.GetString(byData, 0, icData);

case RegistryImpl.REG_EXPAND_SZ:
return UnicodeEncoding.Unicode.GetString(byData, 0, icData);

default:
throw new Exception("Unknown registry type!");
}
}

/// <summary>
/// Retrieves the data associated with the specified value, or null
if the value does not exist.
/// </summary>
/// <param name="val">Name of the value to retrieve.</param>
/// <returns>The data associated with name , or null if the value
does not exist.</returns>
public object GetValue(string val)
{
// just call the overloaded function
return GetValue(val, null);
}

/// <summary>
/// Sets the specified value. The string subKey is not case sensitive.
/// </summary>
/// <param name="valName">Name of value to store data in.</param>
/// <param name="valData">Data to store.</param>
public void SetValue(string valName, object valData)
{
AssertIsOpen();

// find out what type of data we are setting, and call the appropriate
RegSetValueEx function
if (valData is string)
{
char[] chData = ((string)valData).ToCharArray();
byte[] byValData = new byte[UnicodeEncoding.Unicode.GetByteCount(chData)
+ 1];
byValData = UnicodeEncoding.Unicode.GetBytes(chData);
byValData[byValData.GetUpperBound(0)] = 0;

RegistryImpl.RegSetValueEx(m_uiHKey, valName, 0, RegistryImpl.REG_SZ,
byValData, byValData.GetLength(0));
}
else if (valData is byte[])
{
RegistryImpl.RegSetValueEx(m_uiHKey, valName, 0, RegistryImpl.REG_BINARY,
(byte[])valData,
((byte[])valData).GetLength(0));
}
else if (valData is int)
{
byte[] byValData = BitConverter.GetBytes((int)valData);
RegistryImpl.RegSetValueEx(m_uiHKey, valName, 0, RegistryImpl.REG_DWORD,
byValData, byValData.GetLength(0));
}
else
throw new Exception("Unknown type to set!");
}

/// <summary>
/// Retrieves a specified subkey.
/// </summary>
/// <param name="subkey">Name or path of subkey to open.</param>
/// <param name="writeable">Set to true if you need write access
to the key.</param>
/// <returns>The subkey requested, or null if the operation failed.</returns>
public RegistryKey OpenSubKey(string subkey, bool writeable)
{
AssertIsOpen();
uint uiSubHKey = RegistryImpl.OpenKey(m_uiHKey, subkey);
RegistryKey rk = new RegistryKey(uiSubHKey, subkey);
rk.m_bReadOnly = !writeable;
return rk;
}

/// <summary>
/// Retrieves a subkey as read-only.
/// </summary>
/// <param name="subkey">Name or path of subkey to open.</param>
/// <returns>The subkey requested, or null if the operation failed.</returns>
public RegistryKey OpenSubKey(string subkey)
{
// just call the overloaded function
return OpenSubKey(subkey, false);
}

/// <summary>
/// Retrieves the name of the key.
/// </summary>
public string Name
{
get { return m_sName; }
}

#region Implementation of IDisposable

public void Dispose()
{
Close();
}

#endregion

private void AssertIsOpen()
{
if (m_uiHKey == 0)
throw new IOException("The RegistryKey on which this method
is being invoked is closed");
}

/// <summary>
/// Retrieves a string representation of this key.
/// </summary>
/// <returns>A string representing the key. If the specified key
is invalid (cannot be found) then a null value is returned.</returns>
public override string ToString()
{
return Name;
}
}

/// <summary>
/// This class holds root RegistryKeys for the system registry.
/// Use these keys to manipulate the registry.
/// </summary>
public sealed class Registry
{
private static RegistryKey m_CurrentUser =
new RegistryKey((uint)RegistryImpl.RootKey.HKEY_CURRENT_USER,
"HKEY_CURRENT_USER");

private static RegistryKey m_Users = new RegistryKey((uint)RegistryImpl.RootKey.HKEY_USERS,
"HKEY_USERS");

private static RegistryKey m_LocalMachine =
new RegistryKey((uint)RegistryImpl.RootKey.HKEY_LOCAL_MACHINE,
"HKEY_LOCAL_MACHINE");

private static RegistryKey m_ClassesRoot =
new RegistryKey((uint)RegistryImpl.RootKey.HKEY_CLASSES_ROOT,
"HKEY_CLASSES_ROOT");

public static RegistryKey CurrentUser
{
get { return m_CurrentUser; }
}

public static RegistryKey Users
{
get { return m_Users; }
}

public static RegistryKey LocalMachine
{
get { return m_LocalMachine; }
}

public static RegistryKey ClassesRoot
{
get { return m_ClassesRoot; }
}
}

/// <summary>
/// Internal helper class for registry access.
/// </summary>
public class RegistryImpl
{
public enum RootKey : uint
{
HKEY_CLASSES_ROOT = 0x80000000,
HKEY_CURRENT_USER = 0x80000001,
HKEY_LOCAL_MACHINE = 0x80000002,
HKEY_USERS = 0x80000003
}

public enum KeyDisposition : int
{
REG_CREATED_NEW_KEY = 1,
REG_OPENED_EXISTING_KEY = 2
}

internal const int REG_SZ = 1;
internal const int REG_EXPAND_SZ = 2;
internal const int REG_BINARY = 3;
internal const int REG_DWORD = 4;

#region DLL Imports

[DllImport("coredll.dll", EntryPoint = "RegOpenKeyEx")]
public static extern int RegOpenKeyEx(uint hKey, string lpSubKey,
int ulOptions, int samDesired, ref uint phkResult);

[DllImport("coredll", EntryPoint = "RegCreateKeyEx")]
public static extern int RegCreateKeyEx(uint hKey, string lpSubKey,
int lpReserved, string lpClass, int dwOptions,
int samDesired, ref int lpSecurityAttributes,
ref uint phkResult,
ref int lpdwDisposition);

[DllImport("coredll.dll", EntryPoint = "RegEnumKeyEx")]
public static extern int RegEnumKeyEx(uint hKey, int iIndex, char[]
sKeyName,
ref int iKeyNameLen, int iReservedZero,
char[] sClassName, ref int iClassNameLen,
int iFiletimeZero);

[DllImport("coredll.dll", EntryPoint = "RegEnumValue")]
public static extern int RegEnumValue(uint hKey, int iIndex, char[]
sValueName,
ref int iValueNameLen, int
iReservedZero, ref int iType, ref byte[] byData,
ref int iDataLen);

[DllImport("coredll.dll", EntryPoint = "RegQueryInfoKey")]
public static extern int RegQueryInfoKey(uint hKey, char[] lpClass,
ref int lpcbClass,
int reservedZero, ref int
cSubkey, ref int iMaxSubkeyLen,
ref int lpcbMaxSubkeyClassLen,
ref int cValueNames, ref
int iMaxValueNameLen, ref int iMaxValueLen,
int securityDescriptorZero,
int lastWriteTimeZero);

[DllImport("coredll.dll", EntryPoint = "RegQueryValueEx")]
public static extern int RegQueryValueEx(uint hKey, string lpValueName,
int lpReserved, ref int lpType, byte[] lpData,
ref int lpcbData);

[DllImport("coredll.dll", EntryPoint = "RegSetValueExW")]
public static extern int RegSetValueEx(uint hKey, string lpValueName,
int lpReserved, int lpType, byte[] lpData,
int lpcbData);

[DllImport("coredll.dll", EntryPoint = "RegCloseKey")]
public static extern int RegCloseKey(uint hKey);

[DllImport("coredll.dll", EntryPoint = "RegDeleteKey")]
public static extern int RegDeleteKey(uint hKey, string keyName);

[DllImport("coredll.dll", EntryPoint = "RegDeleteValue")]
public static extern int RegDeleteValue(uint hKey, string valueName);

#endregion

/// <summary>
/// Helper to allow me to easily open a key
/// </summary>
/// <param name="RootKey"></param>
/// <param name="SubKey"></param>
/// <returns></returns>
public static uint OpenKey(uint RootKey, string SubKey)
{
uint hKey = 0;
int ret = 0;

try
{
RegOpenKeyEx(RootKey, SubKey, 0, 0, ref hKey);
}
catch (Exception ex)
{
Console.WriteLine("Exception opening key: " + ex.Message);
throw;
}

if (ret != 0)
Console.WriteLine("Failed to open key: " + ret.ToString());

return hKey;
}

/// <summary>
/// Helper to allow me to easily Create a key
/// </summary>
/// <param name="RootKey"></param>
/// <param name="SubKey"></param>
/// <param name="KeyClass"></param>
/// <param name="Disposition"></param>
/// <returns></returns>
public static uint CreateKey(uint RootKey, string SubKey, string
KeyClass, ref KeyDisposition Disposition)
{
uint hKey = 0;
int disp = 0;
int reserved = 0;
int ret = 0;

try
{
ret = RegCreateKeyEx(RootKey, SubKey, 0, KeyClass, 0, 0,
ref reserved, ref hKey, ref disp);
}
catch (Exception ex)
{
Console.WriteLine("Exception creating key: " + ex.Message);
throw;
}

if (ret != 0)
Console.WriteLine("Failed to create key: " + ret.ToString());
else
Disposition = (KeyDisposition)disp;

return hKey;
}
}


Regards,
Christian Resma Helle
http://christian-helle.blogspot.com

Christian Resma Helle

unread,
Nov 12, 2009, 4:18:31 PM11/12/09
to
The code I posted was written in .NETCF 1.0 and can be easily shortened and
optimized if you use .NETCF 2.0 or 3.5. Especially because of the Registry
wrappers being included in .NETCF 2.0 and higher

Regards,
Christian Resma Helle
http://christian-helle.blogspot.com

Christian Resma Helle

unread,
Nov 12, 2009, 4:25:53 PM11/12/09
to
Sorry, I missed the part regarding creating a today screen plugin. I would
recommend doing this in native code, but its also possible in C# as well

Check out these links:
http://www.codeplex.com/ManagedTodayScreen
http://www.christec.co.nz/blog/archives/279


Regards,
Christian Resma Helle
http://christian-helle.blogspot.com

> I am developing application in Windows mobile 6.0, using C# and .NET

0 new messages