├── .gitignore
├── Clippy.sln
├── Clippy.sln.DotSettings
├── Clippy
├── Clippy.cs
├── Clippy.csproj
└── Properties
│ └── AssemblyInfo.cs
├── ClippyTest
├── BasicUsage.cs
├── ClippyTest.csproj
└── Properties
│ └── AssemblyInfo.cs
├── LICENSE
├── README.md
└── Sample
├── App.config
├── Program.cs
├── Properties
└── AssemblyInfo.cs
└── Sample.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | /*.suo
2 | /*.user
3 | /ClippyTest/bin
4 | /ClippyTest/obj
5 | /Clippy/bin
6 | /Clippy/obj
7 | /Sample/obj
8 | /Sample/bin
9 | /bin
10 |
--------------------------------------------------------------------------------
/Clippy.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Clippy", "Clippy\Clippy.csproj", "{B6B651B1-13E1-4682-A303-CD0EB1BB41AF}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClippyTest", "ClippyTest\ClippyTest.csproj", "{F9B4726F-C7D5-4DDE-AF86-7DA246FF1F5A}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample", "Sample\Sample.csproj", "{FE964C0A-C17B-476E-9906-DD12CC3C772F}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9C51FA4F-B589-4093-8E7B-C2C995C8B8D0}"
11 | ProjectSection(SolutionItems) = preProject
12 | LICENSE = LICENSE
13 | README.md = README.md
14 | EndProjectSection
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {B6B651B1-13E1-4682-A303-CD0EB1BB41AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {B6B651B1-13E1-4682-A303-CD0EB1BB41AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {B6B651B1-13E1-4682-A303-CD0EB1BB41AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {B6B651B1-13E1-4682-A303-CD0EB1BB41AF}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {F9B4726F-C7D5-4DDE-AF86-7DA246FF1F5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {F9B4726F-C7D5-4DDE-AF86-7DA246FF1F5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {F9B4726F-C7D5-4DDE-AF86-7DA246FF1F5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {F9B4726F-C7D5-4DDE-AF86-7DA246FF1F5A}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {FE964C0A-C17B-476E-9906-DD12CC3C772F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {FE964C0A-C17B-476E-9906-DD12CC3C772F}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {FE964C0A-C17B-476E-9906-DD12CC3C772F}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {FE964C0A-C17B-476E-9906-DD12CC3C772F}.Release|Any CPU.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/Clippy.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | OK
--------------------------------------------------------------------------------
/Clippy/Clippy.cs:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2014 Kolibri
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | */
25 |
26 | using System;
27 | using System.Runtime.InteropServices;
28 | using System.Text;
29 |
30 | // ReSharper disable once CheckNamespace
31 | namespace Kolibri
32 | {
33 | public class Clippy
34 | {
35 | [DllImport("kernel32.dll")]
36 | private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
37 |
38 | [DllImport("kernel32.dll")]
39 | private static extern uint GetLastError();
40 |
41 | [DllImport("kernel32.dll")]
42 | private static extern IntPtr LocalFree(IntPtr hMem);
43 |
44 | [DllImport("kernel32.dll")]
45 | private static extern IntPtr GlobalFree(IntPtr hMem);
46 |
47 | [DllImport("kernel32.dll")]
48 | private static extern IntPtr GlobalLock(IntPtr hMem);
49 |
50 | [DllImport("kernel32.dll")]
51 | [return: MarshalAs(UnmanagedType.Bool)]
52 | private static extern bool GlobalUnlock(IntPtr hMem);
53 |
54 | [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
55 | public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
56 |
57 | [DllImport("user32.dll")]
58 | [return: MarshalAs(UnmanagedType.Bool)]
59 | private static extern bool OpenClipboard(IntPtr hWndNewOwner);
60 |
61 | [DllImport("user32.dll")]
62 | [return: MarshalAs(UnmanagedType.Bool)]
63 | private static extern bool CloseClipboard();
64 |
65 | [DllImport("user32.dll")]
66 | private static extern IntPtr SetClipboardData(uint uFormat, IntPtr data);
67 |
68 | public enum ResultCode
69 | {
70 | Success = 0,
71 |
72 | ErrorOpenClipboard = 1,
73 | ErrorGlobalAlloc = 2,
74 | ErrorGlobalLock = 3,
75 | ErrorSetClipboardData = 4,
76 | ErrorOutOfMemoryException = 5,
77 | ErrorArgumentOutOfRangeException = 6,
78 | ErrorException = 7,
79 | ErrorInvalidArgs = 8,
80 | ErrorGetLastError = 9
81 | };
82 |
83 | public class Result
84 | {
85 | public ResultCode ResultCode { get; set; }
86 |
87 | public uint LastError { get; set; }
88 |
89 | public bool OK {
90 | // ReSharper disable once RedundantNameQualifier
91 | get { return Clippy.ResultCode.Success == ResultCode; }
92 | }
93 | }
94 |
95 | [STAThread]
96 | public static Result PushStringToClipboard(string message)
97 | {
98 | var isAscii = (message != null && (message == Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(message))));
99 | if (isAscii)
100 | {
101 | return PushUnicodeStringToClipboard(message);
102 | }
103 | else
104 | {
105 | return PushAnsiStringToClipboard(message);
106 | }
107 | }
108 |
109 | [STAThread]
110 | public static Result PushUnicodeStringToClipboard(string message)
111 | {
112 | return __PushStringToClipboard(message, CF_UNICODETEXT);
113 | }
114 |
115 | [STAThread]
116 | public static Result PushAnsiStringToClipboard(string message)
117 | {
118 | return __PushStringToClipboard(message, CF_TEXT);
119 | }
120 |
121 | // ReSharper disable InconsistentNaming
122 | const uint CF_TEXT = 1;
123 | const uint CF_UNICODETEXT = 13;
124 | // ReSharper restore InconsistentNaming
125 |
126 | [STAThread]
127 | private static Result __PushStringToClipboard(string message, uint format)
128 | {
129 | try
130 | {
131 | try
132 | {
133 | if (message == null)
134 | {
135 | return new Result {ResultCode = ResultCode.ErrorInvalidArgs };
136 | }
137 |
138 | if (!OpenClipboard(IntPtr.Zero))
139 | {
140 | return new Result { ResultCode = ResultCode.ErrorOpenClipboard, LastError = GetLastError() };
141 | }
142 |
143 | try
144 | {
145 | uint sizeOfChar;
146 | switch (format)
147 | {
148 | case CF_TEXT:
149 | sizeOfChar = 1;
150 | break;
151 | case CF_UNICODETEXT:
152 | sizeOfChar = 2;
153 | break;
154 | default:
155 | throw new Exception("Not Reachable");
156 | }
157 |
158 | var characters = (uint)message.Length;
159 | uint bytes = (characters + 1) * sizeOfChar;
160 |
161 | // ReSharper disable once InconsistentNaming
162 | const int GMEM_MOVABLE = 0x0002;
163 | // ReSharper disable once InconsistentNaming
164 | const int GMEM_ZEROINIT = 0x0040;
165 | // ReSharper disable once InconsistentNaming
166 | const int GHND = GMEM_MOVABLE | GMEM_ZEROINIT;
167 |
168 | // IMPORTANT: SetClipboardData requires memory that was acquired with GlobalAlloc using GMEM_MOVABLE.
169 | var hGlobal = GlobalAlloc(GHND, (UIntPtr) bytes);
170 | if (hGlobal == IntPtr.Zero)
171 | {
172 | return new Result { ResultCode = ResultCode.ErrorGlobalAlloc, LastError = GetLastError() };
173 | }
174 |
175 | try
176 | {
177 | // IMPORTANT: Marshal.StringToHGlobalUni allocates using LocalAlloc with LMEM_FIXED.
178 | // Note that LMEM_FIXED implies that LocalLock / LocalUnlock is not required.
179 | IntPtr source;
180 | switch (format)
181 | {
182 | case CF_TEXT:
183 | source = Marshal.StringToHGlobalAnsi(message);
184 | break;
185 | case CF_UNICODETEXT:
186 | source = Marshal.StringToHGlobalUni(message);
187 | break;
188 | default:
189 | throw new Exception("Not Reachable");
190 | }
191 |
192 | try
193 | {
194 | var target = GlobalLock(hGlobal);
195 | if (target == IntPtr.Zero)
196 | {
197 | return new Result { ResultCode = ResultCode.ErrorGlobalLock, LastError = GetLastError() };
198 | }
199 |
200 | try
201 | {
202 | CopyMemory(target, source, bytes);
203 | }
204 | finally
205 | {
206 | var ignore = GlobalUnlock(target);
207 | }
208 |
209 | if (SetClipboardData(format, hGlobal).ToInt64() != 0)
210 | {
211 | // IMPORTANT: SetClipboardData takes ownership of hGlobal upon success.
212 | hGlobal = IntPtr.Zero;
213 | }
214 | else
215 | {
216 | return new Result { ResultCode = ResultCode.ErrorSetClipboardData, LastError = GetLastError() };
217 | }
218 | }
219 | finally
220 | {
221 | // Marshal.StringToHGlobalUni actually allocates with LocalAlloc, thus we should theorhetically use LocalFree to free the memory...
222 | // ... but Marshal.FreeHGlobal actully uses a corresponding version of LocalFree internally, so this works, even though it doesn't
223 | // behave exactly as expected.
224 | Marshal.FreeHGlobal(source);
225 | }
226 | }
227 | catch (OutOfMemoryException)
228 | {
229 | return new Result { ResultCode = ResultCode.ErrorOutOfMemoryException, LastError = GetLastError() };
230 | }
231 | catch (ArgumentOutOfRangeException)
232 | {
233 | return new Result { ResultCode = ResultCode.ErrorArgumentOutOfRangeException, LastError = GetLastError() };
234 | }
235 | finally
236 | {
237 | if (hGlobal != IntPtr.Zero)
238 | {
239 | var ignore = GlobalFree(hGlobal);
240 | }
241 | }
242 | }
243 | finally
244 | {
245 | CloseClipboard();
246 | }
247 | return new Result { ResultCode = ResultCode.Success };
248 | }
249 | catch (Exception)
250 | {
251 | return new Result { ResultCode = ResultCode.ErrorException, LastError = GetLastError() };
252 | }
253 | }
254 | catch (Exception)
255 | {
256 | return new Result { ResultCode = ResultCode.ErrorGetLastError };
257 | }
258 | }
259 | }
260 | }
--------------------------------------------------------------------------------
/Clippy/Clippy.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B6B651B1-13E1-4682-A303-CD0EB1BB41AF}
8 | Library
9 | Properties
10 | Clippy
11 | Clippy
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
53 |
--------------------------------------------------------------------------------
/Clippy/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Clippy")]
8 | [assembly: AssemblyDescription("Manipulate the clipboard without using Windows.Forms")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("Kolibri")]
11 | [assembly: AssemblyProduct("Clippy")]
12 | [assembly: AssemblyCopyright("Copyright © 2014 Kolibri")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("b631b2e4-b0c8-45dd-9a14-ff9c0c858518")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/ClippyTest/BasicUsage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Windows.Forms;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 | using Kolibri;
6 |
7 | namespace ClippyTest
8 | {
9 | [TestClass]
10 | public class BasicUsage
11 | {
12 | [TestInitialize]
13 | public void Setup()
14 | {
15 | Clipboard.Clear();
16 | }
17 |
18 | private static readonly string[] clipboardDataFormats =
19 | {
20 | DataFormats.Bitmap,
21 | DataFormats.CommaSeparatedValue,
22 | DataFormats.Dib,
23 | DataFormats.Dif,
24 | DataFormats.EnhancedMetafile,
25 | DataFormats.FileDrop,
26 | DataFormats.Html,
27 | DataFormats.Locale,
28 | DataFormats.MetafilePict,
29 | DataFormats.OemText,
30 | DataFormats.Palette,
31 | DataFormats.PenData,
32 | DataFormats.Riff,
33 | DataFormats.Rtf,
34 | DataFormats.Serializable,
35 | DataFormats.StringFormat,
36 | DataFormats.SymbolicLink,
37 | DataFormats.Text,
38 | DataFormats.Tiff,
39 | DataFormats.UnicodeText,
40 | DataFormats.WaveAudio
41 | };
42 |
43 | private static bool IsClipboardNonEmpty()
44 | {
45 | return clipboardDataFormats.Any(Clipboard.ContainsData);
46 | }
47 |
48 | private static bool IsClipboardEmpty()
49 | {
50 | return !IsClipboardNonEmpty();
51 | }
52 |
53 | [TestMethod]
54 | public void PushNullStringToClipboardIsntAllowed()
55 | {
56 | var result = Clippy.PushStringToClipboard(null);
57 | Assert.IsNotNull(result);
58 | Assert.AreEqual(Clippy.ResultCode.ErrorInvalidArgs, result.ResultCode);
59 | Assert.IsTrue(IsClipboardEmpty());
60 | }
61 |
62 | [TestMethod]
63 | public void PushAsciiStringToClipboardWillBeAscii()
64 | {
65 | var p = "asdf";
66 | var result = Clippy.PushStringToClipboard(p);
67 | Assert.IsNotNull(result);
68 | Assert.IsTrue(result.OK);
69 | Assert.IsTrue(Clipboard.ContainsData(DataFormats.Text));
70 | Assert.IsTrue(Clipboard.GetText() == p);
71 | }
72 |
73 | [TestMethod]
74 | public void PushNonAsciiStringToClipboardWillBeUnicode()
75 | {
76 | var p = "áéíóúýðæö";
77 | var result = Clippy.PushStringToClipboard(p);
78 | Assert.IsNotNull(result);
79 | Assert.IsTrue(result.OK);
80 | Assert.IsTrue(Clipboard.ContainsData(DataFormats.UnicodeText));
81 | Assert.IsTrue(Clipboard.GetText() == p);
82 | }
83 |
84 | [TestMethod]
85 | public void PushEmptyStringToClipboardDoesntBomb()
86 | {
87 | const string p = "";
88 | var result = Clippy.PushStringToClipboard(p);
89 | Assert.IsNotNull(result);
90 | Assert.IsTrue(result.OK);
91 | Assert.IsTrue(Clipboard.ContainsData(DataFormats.UnicodeText));
92 | Assert.IsTrue(Clipboard.GetText() == p);
93 | }
94 |
95 | [TestMethod]
96 | public void PushAnyStringToClipboardDoesntBomb()
97 | {
98 | const string p = "Clippy!";
99 | var result = Clippy.PushStringToClipboard(p);
100 | Assert.IsNotNull(result);
101 | Assert.IsTrue(result.OK);
102 | Assert.IsFalse(IsClipboardEmpty());
103 | Assert.IsTrue(Clipboard.ContainsData(DataFormats.UnicodeText));
104 | Assert.IsTrue(Clipboard.GetText() == p);
105 | }
106 |
107 | private enum WindowsErrorCodes : uint
108 | {
109 | Success = 0,
110 | ErrorNotEnoughMemory = 8
111 | }
112 |
113 | [TestMethod]
114 | public void PushHugeStringToClipboardDoesntBomb()
115 | {
116 | var stuff = "1234567890";
117 | for (var i = 0; i < 99; ++i)
118 | {
119 | var outOfMemory = false;
120 | try
121 | {
122 | stuff += stuff;
123 | }
124 | catch (OutOfMemoryException)
125 | {
126 | outOfMemory = true;
127 | }
128 |
129 | var result = Clippy.PushStringToClipboard(stuff);
130 | Assert.IsNotNull(result);
131 | switch (result.ResultCode)
132 | {
133 | case Clippy.ResultCode.Success:
134 | break;
135 | case Clippy.ResultCode.ErrorGlobalAlloc:
136 | Assert.AreEqual(WindowsErrorCodes.ErrorNotEnoughMemory, (WindowsErrorCodes)result.LastError);
137 | Assert.IsFalse(Clipboard.GetText() == stuff);
138 | break;
139 | case Clippy.ResultCode.ErrorOutOfMemoryException:
140 | Assert.AreEqual(WindowsErrorCodes.Success, (WindowsErrorCodes)result.LastError);
141 | Assert.IsFalse(Clipboard.GetText() == stuff);
142 | break;
143 | default:
144 | Assert.Fail("Unexpected result code ({0}) and windows error ({1})", result.ResultCode, result.LastError);
145 | break;
146 | }
147 |
148 | if (outOfMemory)
149 | {
150 | Assert.IsFalse(result.OK);
151 | }
152 | else
153 | {
154 | if (result.OK)
155 | {
156 | Assert.IsTrue(Clipboard.ContainsData(DataFormats.UnicodeText));
157 | Assert.IsTrue(Clipboard.GetText() == stuff);
158 | }
159 | else
160 | {
161 | Assert.IsFalse(Clipboard.GetText() == stuff);
162 | return;
163 | }
164 | }
165 | }
166 | Assert.Inconclusive();
167 | }
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/ClippyTest/ClippyTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {F9B4726F-C7D5-4DDE-AF86-7DA246FF1F5A}
7 | Library
8 | Properties
9 | ClippyTest
10 | ClippyTest
11 | v4.5
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | {b6b651b1-13e1-4682-a303-cd0eb1bb41af}
60 | Clippy
61 |
62 |
63 |
64 |
65 |
66 |
67 | False
68 |
69 |
70 | False
71 |
72 |
73 | False
74 |
75 |
76 | False
77 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
--------------------------------------------------------------------------------
/ClippyTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ClippyTest")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ClippyTest")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("4fc43340-31ad-4a91-b70e-784a0a9f233a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Kolibri
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | clippy
2 | ======
3 |
4 | Push a string to the Windows clipboard, without the Windows Forms assembly
5 |
--------------------------------------------------------------------------------
/Sample/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Sample/Program.cs:
--------------------------------------------------------------------------------
1 | using Kolibri;
2 |
3 | namespace Sample
4 | {
5 | class Program
6 | {
7 | static void Main(string[] args)
8 | {
9 | if (args.Length > 0)
10 | {
11 | Clippy.PushStringToClipboard(args[0]);
12 | System.Console.WriteLine("pushed \"{0}\" to the clipboard.",args[0]);
13 | }
14 | else
15 | {
16 | System.Console.WriteLine("usage: sample.exe \"\"");
17 | System.Console.WriteLine(" pushes the message onto the clipboard.");
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sample/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Clippy Sample")]
8 | [assembly: AssemblyDescription("Sample application for Clippy. Pushes a string to the clipboard.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("Kolibri")]
11 | [assembly: AssemblyProduct("Clippy")]
12 | [assembly: AssemblyCopyright("Copyright © Kolibri 2014")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("25a09c91-7521-417f-9cab-756b854b068d")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/Sample/Sample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {FE964C0A-C17B-476E-9906-DD12CC3C772F}
8 | Exe
9 | Properties
10 | Sample
11 | Sample
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {b6b651b1-13e1-4682-a303-cd0eb1bb41af}
53 | Clippy
54 |
55 |
56 |
57 |
64 |
--------------------------------------------------------------------------------