Installer, start and exit enhancements

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@762 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2010-08-01 15:33:03 +00:00
commit 49ac48a6e8
5 changed files with 175 additions and 148 deletions

View file

@ -57,7 +57,6 @@ namespace Greenshot.Forms {
private Rectangle captureRect = Rectangle.Empty; private Rectangle captureRect = Rectangle.Empty;
private ICapture capture = null; private ICapture capture = null;
private AppConfig conf = AppConfig.GetInstance(); private AppConfig conf = AppConfig.GetInstance();
private CopyData copyData = null;
private ILanguage lang = Language.GetInstance(); private ILanguage lang = Language.GetInstance();
public CaptureForm() { public CaptureForm() {
@ -65,56 +64,11 @@ namespace Greenshot.Forms {
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
// //
InitializeComponent(); InitializeComponent();
// Create a new instance of the class: copyData = new CopyData();
copyData = new CopyData();
// Assign the handle:
copyData.AssignHandle(this.Handle);
// Create the channel to send on:
copyData.Channels.Add("Greenshot");
// Hook up received event:
copyData.DataReceived += new DataReceivedEventHandler(CopyDataDataReceived);
// Make sure the form is hidden (might be overdoing it...) // Make sure the form is hidden (might be overdoing it...)
this.Hide(); this.Hide();
} }
/// <summary>
/// DataReceivedEventHandler
/// </summary>
/// <param name="sender"></param>
/// <param name="dataReceivedEventArgs"></param>
private void CopyDataDataReceived(object sender, DataReceivedEventArgs dataReceivedEventArgs) {
// Cast the data to the type of object we sent:
DataTransport dataTransport = (DataTransport)dataReceivedEventArgs.Data;
HandleDataTransport(dataTransport);
}
public void HandleDataTransport(DataTransport dataTransport) {
LOG.Debug("Data received, Command = " + dataTransport.Command + ", Data: " + dataTransport.CommandData);
switch(dataTransport.Command) {
case CommandEnum.Exit:
MainForm.instance.exit();
break;
case CommandEnum.ReloadConfig:
AppConfig.Reload();
// Even update language when needed
MainForm.instance.UpdateUI();
break;
case CommandEnum.OpenFile:
string filename = dataTransport.CommandData;
if (File.Exists(filename)) {
MakeCapture(filename);
} else {
LOG.Warn("No such file: " + filename);
}
break;
default:
LOG.Error("Unknown command!");
break;
}
}
void DoCaptureFeedback() { void DoCaptureFeedback() {
if((bool)conf.Ui_Effects_CameraSound) { if((bool)conf.Ui_Effects_CameraSound) {
SoundHelper.Play(); SoundHelper.Play();

View file

@ -49,11 +49,13 @@ namespace Greenshot {
private static log4net.ILog LOG = null; private static log4net.ILog LOG = null;
private static AppConfig conf; private static AppConfig conf;
static Mutex applicationMutex = null; private static Mutex applicationMutex = null;
[STAThread] [STAThread]
public static void Main(string[] args) { public static void Main(string[] args) {
DataTransport dataTransport = null; bool isAlreadyRunning = false;
List<string> filesToOpen = new List<string>();
// Set the Thread name, is better than "1" // Set the Thread name, is better than "1"
Thread.CurrentThread.Name = Application.ProductName; Thread.CurrentThread.Name = Application.ProductName;
@ -74,6 +76,16 @@ namespace Greenshot {
// Log the startup // Log the startup
LOG.Info("Starting: " + EnvironmentInfo.EnvironmentToString(false)); LOG.Info("Starting: " + EnvironmentInfo.EnvironmentToString(false));
try { try {
// Fix for Bug 2495900, Multi-user Environment
// check whether there's an local instance running already
// 1) Create Mutex
applicationMutex = new Mutex(false, @"Local\F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08");
// 2) Get the right to it, this returns false if it's already locked
if (!applicationMutex.WaitOne(0, false)) {
isAlreadyRunning = true;
}
for(int argumentNr = 0; argumentNr < args.Length; argumentNr++) { for(int argumentNr = 0; argumentNr < args.Length; argumentNr++) {
string argument = args[argumentNr]; string argument = args[argumentNr];
@ -106,8 +118,8 @@ namespace Greenshot {
helpOutput.AppendLine("\t\tA detailed listing of available settings for the configure command."); helpOutput.AppendLine("\t\tA detailed listing of available settings for the configure command.");
helpOutput.AppendLine(); helpOutput.AppendLine();
helpOutput.AppendLine(); helpOutput.AppendLine();
helpOutput.AppendLine("\t--uninstall"); helpOutput.AppendLine("\t--exit");
helpOutput.AppendLine("\t\tUnstall is called from the unstaller and tries to close all running instances."); helpOutput.AppendLine("\t\tTries to close all running instances.");
helpOutput.AppendLine(); helpOutput.AppendLine();
helpOutput.AppendLine(); helpOutput.AppendLine();
helpOutput.AppendLine("\t--configure [property=value] ..."); helpOutput.AppendLine("\t--configure [property=value] ...");
@ -120,7 +132,7 @@ namespace Greenshot {
helpOutput.AppendLine("\t\tOpen the bitmap file in the running Greenshot instance or start a new instance"); helpOutput.AppendLine("\t\tOpen the bitmap file in the running Greenshot instance or start a new instance");
helpOutput.AppendLine(); helpOutput.AppendLine();
helpOutput.AppendLine(); helpOutput.AppendLine();
helpOutput.AppendLine("\t--exit"); helpOutput.AppendLine("\t--norun");
helpOutput.AppendLine("\t\tCan be used if someone only wants to change the configuration."); helpOutput.AppendLine("\t\tCan be used if someone only wants to change the configuration.");
helpOutput.AppendLine("\t\tAs soon as this option is found Greenshot exits if not and there is no running instance it will stay running."); helpOutput.AppendLine("\t\tAs soon as this option is found Greenshot exits if not and there is no running instance it will stay running.");
helpOutput.AppendLine("\t\tExample: greenshot.exe --configure Output_File_Path=\"C:\\Documents and Settings\\\" --exit"); helpOutput.AppendLine("\t\tExample: greenshot.exe --configure Output_File_Path=\"C:\\Documents and Settings\\\" --exit");
@ -131,19 +143,20 @@ namespace Greenshot {
if (!attachedToConsole) { if (!attachedToConsole) {
Console.ReadKey(); Console.ReadKey();
} }
FreeMutex();
return; return;
} }
// unregister application on uninstall (allow uninstall) // exit application
if (argument.Equals("--uninstall") || argument.Equals("uninstall")) { if (argument.Equals("--exit")) {
try { try {
LOG.Info("Sending all instances the exit command."); LOG.Info("Sending all instances the exit command.");
// Pass Exit to running instance, if any // Pass Exit to running instance, if any
dataTransport = new DataTransport(CommandEnum.Exit, args[0]); SendData(new CopyDataTransport(CommandEnum.Exit));
SendData(dataTransport);
} catch (Exception e) { } catch (Exception e) {
LOG.Warn("Exception by exit.", e); LOG.Warn("Exception by exit.", e);
} }
FreeMutex();
return; return;
} }
@ -165,7 +178,7 @@ namespace Greenshot {
conf.SetProperties(properties); conf.SetProperties(properties);
conf.Store(); conf.Store();
// Update running instances // Update running instances
SendData(new DataTransport(CommandEnum.ReloadConfig)); SendData(new CopyDataTransport(CommandEnum.ReloadConfig));
LOG.Debug("Configuration modified!"); LOG.Debug("Configuration modified!");
} else { } else {
LOG.Debug("Configuration NOT modified!"); LOG.Debug("Configuration NOT modified!");
@ -173,33 +186,38 @@ namespace Greenshot {
} }
// Make an exit possible // Make an exit possible
if (argument.Equals("--exit")) { if (argument.Equals("--norun")) {
FreeMutex();
return; return;
} }
if (argument.Equals("--openfile")) { if (argument.Equals("--openfile")) {
// Take filename and send it to running instance or take it while opening string filename = args[++argumentNr];
dataTransport = new DataTransport(CommandEnum.OpenFile, args[0]); filesToOpen.Add(filename);
} }
} }
// Fix for Bug 2495900, Multi-user Environment // Finished parsing the command line arguments, see if we need to do anything
// check whether there's an local instance running already CopyDataTransport transport = new CopyDataTransport();
if (filesToOpen.Count > 0) {
// 1) Create Mutex foreach(string fileToOpen in filesToOpen) {
applicationMutex = new Mutex(false, @"Local\F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08"); transport.AddCommand(CommandEnum.OpenFile, fileToOpen);
// 2) Get the right to it, this returns false if it's already locked }
if (!applicationMutex.WaitOne(0, false)) { }
if (dataTransport != null) { if (isAlreadyRunning) {
SendData(dataTransport); if (filesToOpen.Count > 0) {
} else { SendData(transport);
} else {
conf = AppConfig.GetInstance(); conf = AppConfig.GetInstance();
ILanguage lang = Language.GetInstance(); ILanguage lang = Language.GetInstance();
MessageBox.Show(lang.GetString(LangKey.error_multipleinstances), lang.GetString(LangKey.error)); MessageBox.Show(lang.GetString(LangKey.error_multipleinstances), lang.GetString(LangKey.error));
} }
FreeMutex();
Application.Exit(); Application.Exit();
return; return;
} }
// From here on we continue starting Greenshot
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
@ -216,20 +234,11 @@ namespace Greenshot {
// Check if it's the first time launch? // Check if it's the first time launch?
bool firstLaunch = (bool)conf.General_IsFirstLaunch; bool firstLaunch = (bool)conf.General_IsFirstLaunch;
if(firstLaunch) { if(firstLaunch) {
// todo: display basic instructions conf.General_IsFirstLaunch = false;
try { conf.Store();
} catch (Exception ex) { transport.AddCommand(CommandEnum.FirstLaunch);
LOG.Error("Exception in MainForm.", ex);
} finally {
conf.General_IsFirstLaunch = false;
conf.Store();
}
} }
// Pass firstlaunch if it is the firstlaunch and no filename is given MainForm mainForm = new MainForm(transport);
if (dataTransport == null && firstLaunch) {
dataTransport = new DataTransport(CommandEnum.FirstLaunch, null);
}
MainForm mainForm = new MainForm(dataTransport);
Application.Run(mainForm); Application.Run(mainForm);
} catch(Exception ex) { } catch(Exception ex) {
LOG.Error("Exception in startup.", ex); LOG.Error("Exception in startup.", ex);
@ -241,21 +250,34 @@ namespace Greenshot {
/// Send DataTransport Object via Window-messages /// Send DataTransport Object via Window-messages
/// </summary> /// </summary>
/// <param name="dataTransport">DataTransport with data for a running instance</param> /// <param name="dataTransport">DataTransport with data for a running instance</param>
private static void SendData(DataTransport dataTransport) { private static void SendData(CopyDataTransport copyDataTransport) {
string appName = Application.ProductName; string appName = Application.ProductName;
CopyData copyData = new CopyData(); CopyData copyData = new CopyData();
copyData.Channels.Add(appName); copyData.Channels.Add(appName);
copyData.Channels[appName].Send(dataTransport); copyData.Channels[appName].Send(copyDataTransport);
} }
private static void FreeMutex() {
// Remove the application mutex
if (applicationMutex != null) {
try {
applicationMutex.ReleaseMutex();
applicationMutex = null;
} catch (Exception ex) {
LOG.Error("Error releasing Mutex!", ex);
}
}
}
public static MainForm instance = null; public static MainForm instance = null;
private ILanguage lang; private ILanguage lang;
private ToolTip tooltip; private ToolTip tooltip;
private CaptureForm captureForm = null; private CaptureForm captureForm = null;
private string lastImagePath = null; private string lastImagePath = null;
private CopyData copyData = null;
public MainForm(DataTransport dataTransport) {
public MainForm(CopyDataTransport dataTransport) {
instance = this; instance = this;
// //
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
@ -280,21 +302,60 @@ namespace Greenshot {
// Enable the Greenshot icon to be visible, this prevents Problems with the context menu // Enable the Greenshot icon to be visible, this prevents Problems with the context menu
notifyIcon.Visible = true; notifyIcon.Visible = true;
// Create a new instance of the class: copyData = new CopyData();
copyData = new CopyData();
// Assign the handle:
copyData.AssignHandle(this.Handle);
// Create the channel to send on:
copyData.Channels.Add("Greenshot");
// Hook up received event:
copyData.CopyDataReceived += new CopyDataReceivedEventHandler(CopyDataDataReceived);
if (dataTransport != null) { if (dataTransport != null) {
// See what the dataTransport from the static main brought us! HandleDataTransport(dataTransport);
switch (dataTransport.Command) { }
case CommandEnum.FirstLaunch: }
// Show user where Greenshot is, only at first start
notifyIcon.ShowBalloonTip(3000, "Greenshot", lang.GetString(LangKey.tooltip_firststart), ToolTipIcon.Info); /// <summary>
/// DataReceivedEventHandler
/// </summary>
/// <param name="sender"></param>
/// <param name="dataReceivedEventArgs"></param>
private void CopyDataDataReceived(object sender, CopyDataReceivedEventArgs copyDataReceivedEventArgs) {
// Cast the data to the type of object we sent:
CopyDataTransport dataTransport = (CopyDataTransport)copyDataReceivedEventArgs.Data;
HandleDataTransport(dataTransport);
}
private void HandleDataTransport(CopyDataTransport dataTransport) {
foreach(KeyValuePair<CommandEnum, string> command in dataTransport.Commands) {
LOG.Debug("Data received, Command = " + command.Key + ", Data: " + command.Value);
switch(command.Key) {
case CommandEnum.Exit:
exit();
break;
case CommandEnum.ReloadConfig:
AppConfig.Reload();
// Even update language when needed
UpdateUI();
break; break;
case CommandEnum.OpenFile: case CommandEnum.OpenFile:
captureForm.HandleDataTransport(dataTransport); string filename = command.Value;
if (File.Exists(filename)) {
captureForm.MakeCapture(filename);
} else {
LOG.Warn("No such file: " + filename);
}
break;
default:
LOG.Error("Unknown command!");
break; break;
} }
} }
} }
public ContextMenuStrip MainMenu { public ContextMenuStrip MainMenu {
get {return contextMenu;} get {return contextMenu;}
} }
@ -577,14 +638,7 @@ namespace Greenshot {
LOG.Error("Error storing configuration!", e); LOG.Error("Error storing configuration!", e);
} }
// Remove the application mutex // Remove the application mutex
if (applicationMutex != null) { FreeMutex();
try {
applicationMutex.ReleaseMutex();
applicationMutex = null;
} catch (Exception ex) {
LOG.Error("Error releasing Mutex!", ex);
}
}
// make the icon invisible otherwise it stays even after exit!! // make the icon invisible otherwise it stays even after exit!!
if (notifyIcon != null) { if (notifyIcon != null) {

View file

@ -3,7 +3,7 @@ Here are some details about Greenshot that might be handy for silent/mass instal
The Greenshot installer is made with Inno Setup, see http://www.jrsoftware.org/isinfo.php The Greenshot installer is made with Inno Setup, see http://www.jrsoftware.org/isinfo.php
For command line options of the installer see: http://www.jrsoftware.org/ishelp/index.php?topic=setupcmdline For command line options of the installer see: http://www.jrsoftware.org/ishelp/index.php?topic=setupcmdline
Since Greenshot build > 0.8.0.700 it is possible to configure Greenshot settings from the command-line. Since Greenshot 0.8.1 it is possible to configure Greenshot settings from the command-line.
This will even work when Greenshot is already running! This will even work when Greenshot is already running!
Greenshot commandline options: Greenshot commandline options:
@ -14,19 +14,21 @@ Greenshot commandline options:
--help configure --help configure
A list of the options that can be set A list of the options that can be set
--uninstall --exit
Unstall is called from the unstaller and tries to close all running instances. Try to close all running instances, could be used for installers
--configure [property=value] ... --configure [property=value] ...
Change the configuration of Greenshot via the commandline, multiple properties can be specified after each other. Change the configuration of Greenshot via the commandline, multiple properties can be specified after each other.
Example to change the language to English: greenshot.exe --configure Ui_Language=en-US Example to change the language to English: greenshot.exe --configure Ui_Language=en-US
Example to change the destination: greenshot.exe --configure Output_File_Path="C:\Documents and Settings\" Example to change the destination: greenshot.exe --configure Output_File_Path="C:\Documents and Settings\"
--openfile [filename] --openfile [filename]
Open the bitmap file in the running Greenshot instance or start a new instance Open the bitmap file in the running Greenshot instance or start a new instance
--norun
Use as last option if you don't want the started executable to spawn a Greenshot instance.
e.g. when you only want to change settings but don't want to have a running Greenshot afterwards.
With the --configure option many settings can be change, the --help configure will give a list of all available settings! With the --configure option many settings can be change, the --help configure will give a list of all available settings!
Here are some described in detail: Here are some described in detail:

View file

@ -29,6 +29,8 @@ AppSupportURL=http://getgreenshot.org
AppUpdatesURL=http://getgreenshot.org AppUpdatesURL=http://getgreenshot.org
AppVerName={#ExeName} {#Version} AppVerName={#ExeName} {#Version}
AppVersion={#Version} AppVersion={#Version}
; changes associations is used when the installer installs new extensions, it clears the explorer icon cache
;ChangesAssociations=yes
Compression=lzma/ultra64 Compression=lzma/ultra64
InternalCompressLevel=ultra64 InternalCompressLevel=ultra64
LanguageDetectionMethod=uilanguage LanguageDetectionMethod=uilanguage
@ -38,7 +40,7 @@ VersionInfoCompany={#ExeName}
VersionInfoTextVersion={#Version} VersionInfoTextVersion={#Version}
VersionInfoVersion={#Version} VersionInfoVersion={#Version}
VersionInfoProductName={#ExeName} VersionInfoProductName={#ExeName}
PrivilegesRequired=admin PrivilegesRequired=poweruser
; Reference a bitmap, max size 164x314 ; Reference a bitmap, max size 164x314
WizardImageFile=installer-large.bmp WizardImageFile=installer-large.bmp
; Reference a bitmap, max size 55x58 ; Reference a bitmap, max size 55x58
@ -46,6 +48,11 @@ WizardSmallImageFile=installer-small.bmp
MinVersion=,5.01.2600 MinVersion=,5.01.2600
[Registry] [Registry]
Root: HKCU; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: {#ExeName}; ValueData: {app}\{#ExeName}.exe; Permissions: users-modify; Flags: uninsdeletevalue; Tasks: startup Root: HKCU; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: {#ExeName}; ValueData: {app}\{#ExeName}.exe; Permissions: users-modify; Flags: uninsdeletevalue; Tasks: startup
; Register our own filetype
;Root: HKCR; Subkey: ".gsb"; ValueType: string; ValueName: ""; ValueData: "GreenshotFile"; Flags: uninsdeletevalue
;Root: HKCR; Subkey: "GreenshotFile"; ValueType: string; ValueName: ""; ValueData: "Greenshot File"; Flags: uninsdeletekey
;Root: HKCR; Subkey: "GreenshotFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Greenshot.EXE,0"
;Root: HKCR; Subkey: "GreenshotFile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""
[Icons] [Icons]
Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app} Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app}
Name: {group}\Uninstall {#ExeName}; Filename: {app}\unins000.exe; WorkingDir: {app} Name: {group}\Uninstall {#ExeName}; Filename: {app}\unins000.exe; WorkingDir: {app}
@ -80,47 +87,49 @@ Name: "plugins\ocr"; Description: {cm:ocr}; Types: Full
Name: "plugins\titlefix"; Description: {cm:titlefix}; Types: Full Name: "plugins\titlefix"; Description: {cm:titlefix}; Types: Full
;Name: "plugins\flickr"; Description: "Flickr Plugin"; Types: Full ;Name: "plugins\flickr"; Description: "Flickr Plugin"; Types: Full
[Code] [Code]
function InitializeSetup(): Boolean; function KillGreenshot() : Boolean;
var var
ErrorCode : Integer;
NetFrameWorkInstalled : Boolean;
MsgBoxResult : Boolean;
bMutex : Boolean; bMutex : Boolean;
resultCode: Integer; resultCode: Integer;
begin begin
bMutex:= True
NetFrameWorkInstalled := RegKeyExists(HKLM, 'SOFTWARE\Microsoft\.NETFramework\policy\v2.0'); while bMutex do
if NetFrameWorkInstalled = true then
begin begin
bMutex:= CheckForMutexes ('Local\{#Mutex}'); bMutex:= CheckForMutexes ('Local\{#Mutex}');
if bMutex = True then if bMutex = True then
begin begin
Exec('taskkill.exe', '/F /IM Greenshot.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); Exec('taskkill.exe', '/F /IM Greenshot.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
Sleep(1200);
end; end;
Result := true;
end; end;
Result := True;
end;
if NetFrameWorkInstalled = false then function InitializeSetup(): Boolean;
begin var
ErrorCode : Integer;
NetFrameWorkInstalled : Boolean;
MsgBoxResult : Boolean;
begin
NetFrameWorkInstalled := RegKeyExists(HKLM, 'SOFTWARE\Microsoft\.NETFramework\policy\v2.0');
if NetFrameWorkInstalled = true then begin
KillGreenshot();
Result := true;
end
else begin
MsgBoxResult := MsgBox(ExpandConstant('{cm:dotnetmissing}'), mbConfirmation, MB_YESNO) = idYes; MsgBoxResult := MsgBox(ExpandConstant('{cm:dotnetmissing}'), mbConfirmation, MB_YESNO) = idYes;
Result := false; Result := false;
if MsgBoxResult = true then if MsgBoxResult = true then
begin begin
ShellExec('open', 'http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe', '','',SW_SHOWNORMAL,ewNoWait,ErrorCode); ShellExec('open', 'http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end; end;
end; end;
end; end;
function InitializeUninstall():Boolean; function InitializeUninstall():Boolean;
var
bMutex : Boolean;
resultCode: Integer;
begin begin
bMutex:= CheckForMutexes ('Local\{#Mutex}'); KillGreenshot();
if bMutex = True then
begin
Exec(ExpandConstant('{app}\{#ExeName}.exe'), '--uninstall', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
Result := True; Result := True;
end; end;
[Run] [Run]

View file

@ -20,6 +20,7 @@
*/ */
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Binary;
@ -34,25 +35,32 @@ namespace Greenshot.Helpers {
public enum CommandEnum { OpenFile, Exit, FirstLaunch, ReloadConfig }; public enum CommandEnum { OpenFile, Exit, FirstLaunch, ReloadConfig };
[Serializable()] [Serializable()]
public class DataTransport { public class CopyDataTransport {
private CommandEnum command; List<KeyValuePair<CommandEnum, string>> commands;
private string commandData; public List<KeyValuePair<CommandEnum, string>> Commands {
public CommandEnum Command { get {return commands;}
get {return command;}
} }
public string CommandData { public CopyDataTransport() {
get {return commandData;} this.commands = new List<KeyValuePair<CommandEnum, string>>();
} }
public DataTransport(CommandEnum command) {
this.command = command; public CopyDataTransport(CommandEnum command) : this() {
AddCommand(command, null);
} }
public DataTransport(CommandEnum command, string commandData) : this(command){ public CopyDataTransport(CommandEnum command, string commandData) : this() {
this.commandData = commandData; AddCommand(command, commandData);
} }
public void AddCommand(CommandEnum command) {
this.commands.Add(new KeyValuePair<CommandEnum, string>(command, null));
}
public void AddCommand(CommandEnum command, string commandData) {
this.commands.Add(new KeyValuePair<CommandEnum, string>(command, commandData));
}
} }
public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e); public delegate void CopyDataReceivedEventHandler(object sender, CopyDataReceivedEventArgs e);
/// <summary> /// <summary>
/// A class which wraps using Windows native WM_COPYDATA /// A class which wraps using Windows native WM_COPYDATA
@ -68,7 +76,7 @@ namespace Greenshot.Helpers {
/// Event raised when data is received on any of the channels /// Event raised when data is received on any of the channels
/// this class is subscribed to. /// this class is subscribed to.
/// </summary> /// </summary>
public event DataReceivedEventHandler DataReceived; public event CopyDataReceivedEventHandler CopyDataReceived;
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
private struct COPYDATASTRUCT { private struct COPYDATASTRUCT {
@ -102,8 +110,8 @@ namespace Greenshot.Helpers {
CopyDataObjectData cdo = (CopyDataObjectData) b.Deserialize(stream); CopyDataObjectData cdo = (CopyDataObjectData) b.Deserialize(stream);
if (channels.Contains(cdo.Channel)) { if (channels.Contains(cdo.Channel)) {
DataReceivedEventArgs d = new DataReceivedEventArgs(cdo.Channel, cdo.Data, cdo.Sent); CopyDataReceivedEventArgs d = new CopyDataReceivedEventArgs(cdo.Channel, cdo.Data, cdo.Sent);
OnDataReceived(d); OnCopyDataReceived(d);
m.Result = (IntPtr) 1; m.Result = (IntPtr) 1;
} }
} }
@ -121,8 +129,8 @@ namespace Greenshot.Helpers {
/// Raises the DataReceived event from this class. /// Raises the DataReceived event from this class.
/// </summary> /// </summary>
/// <param name="e">The data which has been received.</param> /// <param name="e">The data which has been received.</param>
protected void OnDataReceived(DataReceivedEventArgs e) { protected void OnCopyDataReceived(CopyDataReceivedEventArgs e) {
DataReceived(this, e); CopyDataReceived(this, e);
} }
/// <summary> /// <summary>
@ -180,7 +188,7 @@ namespace Greenshot.Helpers {
/// Contains data and other information associated with data /// Contains data and other information associated with data
/// which has been sent from another application. /// which has been sent from another application.
/// </summary> /// </summary>
public class DataReceivedEventArgs { public class CopyDataReceivedEventArgs {
private string channelName = ""; private string channelName = "";
private object data = null; private object data = null;
private DateTime sent; private DateTime sent;
@ -226,7 +234,7 @@ namespace Greenshot.Helpers {
/// <param name="channelName">The channel that the data was received from</param> /// <param name="channelName">The channel that the data was received from</param>
/// <param name="data">The data which was sent</param> /// <param name="data">The data which was sent</param>
/// <param name="sent">The date and time the data was sent</param> /// <param name="sent">The date and time the data was sent</param>
internal DataReceivedEventArgs(string channelName, object data, DateTime sent) { internal CopyDataReceivedEventArgs(string channelName, object data, DateTime sent) {
this.channelName = channelName; this.channelName = channelName;
this.data = data; this.data = data;
this.sent = sent; this.sent = sent;