├── .gitignore
├── LICENSE
├── README.md
├── RemoteView.sln
├── RemoteView
├── App.config
├── Configuration.cs
├── NativeMethods.cs
├── PageHandlers
│ ├── AbstractPageHandler.cs
│ ├── HomePageHandler.cs
│ ├── IconPageHandler.cs
│ ├── InfoPageHandler.cs
│ ├── JavascriptPageHandler.cs
│ ├── LeftClickPageHandler.cs
│ ├── MouseMovePageHandler.cs
│ ├── NotFoundPageHandler.cs
│ ├── RightClickPageHandler.cs
│ └── ScreenPageHandler.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── RemoteView.csproj
├── Server.cs
└── app.manifest
├── StaticAnalysis.fxcop
└── TODO.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Remote Viewer - Desktop sharing software
2 | Copyright (C) 2013 Joao Vilaca
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | RemoteView
2 | ==========
3 |
4 | Desktop sharing HTTP server.
5 |
6 | No need for a dedicated client, any modern browser will do.
7 |
8 | Licensed as GPL. See license file or .
9 |
10 |
11 | Running the Server Application
12 | ==============================
13 |
14 | Syntax: RemoteView [Port to listen] [Options]
15 |
16 | Example: RemoteView 6060 -b
17 |
18 | Options:
19 |
20 | -ip : Bind ip;
21 |
22 | -b : Don't show banner message;
23 |
24 | -m : Allow multiple instances;
25 |
26 | -h : Help (This screen);
27 |
28 |
29 | Requirements
30 | ============
31 |
32 | Server has been tested in both Windows XP 32 bits and Windows 7 64 bits. DotNet Framework 2.0 or better needed.
33 |
34 | Client has been tested with Chrome on the same Windows configurations as above but "should" work in any browser/OS combination.
35 |
36 |
37 | Project Status
38 | ==============
39 |
40 | This application is already somewhat functional but a few features and code quality assurance are still needed.
41 |
42 | See [TODO file](https://github.com/vilaca/RemoteView/blob/master/TODO.md) for more info.
43 |
44 |
45 | Contributors Wanted
46 | ===================
47 |
48 | If you find this project interesting or that in any wait it could be useful for you and want to contribute please do.
49 |
50 | The following roles are needed and open for contributors:
51 |
52 | - C# developer;
53 | - Beta tester;
54 | - Code reviewer.
55 |
56 | See [TODO file](https://github.com/vilaca/RemoteView/blob/master/TODO.md) for more info on pending tasks.
57 |
58 |
59 | How does the Application work ?
60 | ===============================
61 |
62 | This Application is basically an embedded HTTP server that generates a simple HTML5 page with an image. That image is a representation of the current Screen Device of the Server.
63 |
64 | The user sees the remote computer Desktop as a webpage on the browser. Clicks on the browser are sent to the remote computer.
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/RemoteView.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteView", "RemoteView\RemoteView.csproj", "{5DA6855A-DDE4-4F77-BB8D-BC3D39412005}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {5DA6855A-DDE4-4F77-BB8D-BC3D39412005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {5DA6855A-DDE4-4F77-BB8D-BC3D39412005}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {5DA6855A-DDE4-4F77-BB8D-BC3D39412005}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {5DA6855A-DDE4-4F77-BB8D-BC3D39412005}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/RemoteView/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RemoteView/Configuration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Globalization;
4 |
5 | namespace RemoteView
6 | {
7 | class Configuration
8 | {
9 | ///
10 | /// Allow multiple instances of process
11 | ///
12 | public bool AllowMultiple { get; private set; }
13 |
14 | ///
15 | /// Display banner
16 | ///
17 | public bool Banner { get; private set; }
18 |
19 | ///
20 | /// Display help
21 | ///
22 | public bool Help { get; private set; }
23 |
24 | ///
25 | /// Port where to listen
26 | ///
27 | public int Port { get; private set; }
28 |
29 | ///
30 | /// Gets the ip address.
31 | ///
32 | /// The ip address.
33 | public string IpAddress { get; private set; }
34 |
35 | ///
36 | /// Private c'tor with default values for object instances
37 | /// Use factory method instead of instatiating c'tor
38 | ///
39 | private Configuration()
40 | {
41 | this.AllowMultiple = false;
42 | this.Banner = true;
43 | this.Help = false;
44 | this.Port = 6060;
45 | this.IpAddress = "*";
46 | }
47 |
48 | public static Configuration create(string[] parameters)
49 | {
50 | Configuration conf = new Configuration();
51 |
52 | // use default configuration if no parameters exist
53 |
54 | if (parameters.Length == 0)
55 | return conf;
56 |
57 | // cycle throught command line using enumerator on parameters array
58 |
59 | IEnumerator enumerator = parameters.GetEnumerator();
60 | enumerator.MoveNext();
61 |
62 | string parameter = (string)enumerator.Current;
63 |
64 | // parse if first parameter is a valid integer and use it as a port number for listener
65 |
66 | int port;
67 | bool hasPortParameter = int.TryParse(parameter, out port);
68 |
69 | if (hasPortParameter)
70 | {
71 | conf.Port = port;
72 |
73 | // continue parsing parameters (if they exist)
74 | if (!enumerator.MoveNext())
75 | return conf;
76 | parameter = (string)enumerator.Current;
77 | }
78 |
79 | do
80 | {
81 | if (parameter.Equals("-m"))
82 | {
83 | conf.AllowMultiple = true;
84 | }
85 | else if (parameter.Equals("-b"))
86 | {
87 | conf.Banner = false;
88 | }
89 | else if (parameter.Equals("-h"))
90 | {
91 | conf.Help = true;
92 | }
93 | else if (parameter.Equals("-ip"))
94 | {
95 | enumerator.MoveNext();
96 | conf.IpAddress = (string)enumerator.Current;
97 | }
98 | else
99 | {
100 | throw new ArgumentException(string.Format("Error: {0} is an invalid command line parameter.", parameter));
101 | }
102 |
103 | parameter = (string)enumerator.Current;
104 | } while (enumerator.MoveNext());
105 |
106 | return conf;
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/RemoteView/NativeMethods.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Net;
4 | using System.Runtime.InteropServices;
5 | using System.Windows.Forms;
6 |
7 | namespace RemoteView
8 | {
9 |
10 | ///
11 | /// This class is heavily based on source code presented as an answer at
12 | /// http://stackoverflow.com/questions/8021954/sendinput-doesnt-perform-click-mouse-button-unless-i-move-cursor
13 | ///
14 | class NativeMethods
15 | {
16 | ///
17 | /// Don't allow instatiation of this class
18 | ///
19 | private NativeMethods()
20 | {
21 | }
22 |
23 | enum SystemMetric
24 | {
25 | SM_CXSCREEN = 0,
26 | SM_CYSCREEN = 1,
27 | }
28 |
29 | [DllImport("user32.dll")]
30 | static extern int GetSystemMetrics(SystemMetric smIndex);
31 |
32 | [DllImport("user32.dll", SetLastError = true)]
33 | static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
34 |
35 | [StructLayout(LayoutKind.Sequential)]
36 | public struct HARDWAREINPUT
37 | {
38 | public int uMsg;
39 | public short wParamL;
40 | public short wParamH;
41 | }
42 |
43 | [StructLayout(LayoutKind.Sequential)]
44 | public struct KEYBDINPUT
45 | {
46 | public ushort wVk;
47 | public ushort wScan;
48 | public uint dwFlags;
49 | public uint time;
50 | public IntPtr dwExtraInfo;
51 | }
52 |
53 | [StructLayout(LayoutKind.Explicit)]
54 | public struct MouseKeybdhardwareInputUnion
55 | {
56 | [FieldOffset(0)]
57 | public MouseInputData mi;
58 |
59 | [FieldOffset(0)]
60 | public KEYBDINPUT ki;
61 |
62 | [FieldOffset(0)]
63 | public HARDWAREINPUT hi;
64 | }
65 |
66 | [StructLayout(LayoutKind.Sequential)]
67 | public struct INPUT
68 | {
69 | public SendInputEventType type;
70 | public MouseKeybdhardwareInputUnion mkhi;
71 | }
72 |
73 | [Flags]
74 | public enum MouseEventFlags : uint
75 | {
76 | MOUSEEVENTF_MOVE = 0x0001,
77 | MOUSEEVENTF_LEFTDOWN = 0x0002,
78 | MOUSEEVENTF_LEFTUP = 0x0004,
79 | MOUSEEVENTF_RIGHTDOWN = 0x0008,
80 | MOUSEEVENTF_RIGHTUP = 0x0010,
81 | MOUSEEVENTF_MIDDLEDOWN = 0x0020,
82 | MOUSEEVENTF_MIDDLEUP = 0x0040,
83 | MOUSEEVENTF_XDOWN = 0x0080,
84 | MOUSEEVENTF_XUP = 0x0100,
85 | MOUSEEVENTF_WHEEL = 0x0800,
86 | MOUSEEVENTF_VIRTUALDESK = 0x4000,
87 | MOUSEEVENTF_ABSOLUTE = 0x8000
88 | }
89 |
90 | public enum SendInputEventType : int
91 | {
92 | InputMouse,
93 | InputKeyboard,
94 | InputHardware
95 | }
96 |
97 | public struct MouseInputData
98 | {
99 | public int dx;
100 | public int dy;
101 | public uint mouseData;
102 | public MouseEventFlags dwFlags;
103 | public uint time;
104 | public IntPtr dwExtraInfo;
105 | }
106 |
107 | public static int CalculateAbsoluteCoordinateX(int x)
108 | {
109 | return (x * 65536) / GetSystemMetrics(SystemMetric.SM_CXSCREEN);
110 | }
111 |
112 | public static int CalculateAbsoluteCoordinateY(int y)
113 | {
114 | return (y * 65536) / GetSystemMetrics(SystemMetric.SM_CYSCREEN);
115 | }
116 |
117 | public static void LeftMouseButton(MouseEventFlags mouseEventFlags, int x, int y)
118 | {
119 | INPUT mouseInput = new INPUT();
120 | mouseInput.type = SendInputEventType.InputMouse;
121 | mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x);
122 | mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y);
123 | mouseInput.mkhi.mi.mouseData = 0;
124 |
125 | mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE | MouseEventFlags.MOUSEEVENTF_ABSOLUTE;
126 | SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
127 |
128 | mouseInput.mkhi.mi.dwFlags = mouseEventFlags;
129 | SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
130 | }
131 |
132 | public static void ClickRightMouseButton(int x, int y)
133 | {
134 | INPUT mouseInput = new INPUT();
135 | mouseInput.type = SendInputEventType.InputMouse;
136 | mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x);
137 | mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y);
138 | mouseInput.mkhi.mi.mouseData = 0;
139 |
140 | mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE | MouseEventFlags.MOUSEEVENTF_ABSOLUTE;
141 | SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
142 |
143 | mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTDOWN;
144 | SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
145 |
146 | mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTUP;
147 | SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
148 | }
149 |
150 | public static void MoveMouse(int x, int y)
151 | {
152 | INPUT mouseInput = new INPUT();
153 | mouseInput.type = SendInputEventType.InputMouse;
154 | mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x);
155 | mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y);
156 | mouseInput.mkhi.mi.mouseData = 0;
157 |
158 | mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE | MouseEventFlags.MOUSEEVENTF_ABSOLUTE;
159 | SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
160 |
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/RemoteView/PageHandlers/AbstractPageHandler.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Globalization;
4 | using System.Net;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace RemoteView.PageHandlers
9 | {
10 | ///
11 | /// base class for all the request handlers
12 | ///
13 | abstract class AbstractPageHandler
14 | {
15 | ///
16 | ///
17 | ///
18 | /// response to be sent to client
19 | /// tokenized request URI
20 | /// response body
21 | public abstract byte[] HandleRequest(HttpListenerResponse response, String[] uri);
22 |
23 | ///
24 | /// Parse from tokenized URI the selected Screen Device.
25 | /// Default to 0 if parameter not present or error
26 | ///
27 | /// tokenized URI
28 | /// system screens
29 | /// selected screen or default(0)
30 | internal static int GetRequestedScreenDevice(String[] uri, Screen[] screens)
31 | {
32 | int screen = 0;
33 | if (uri.Length > 2)
34 | {
35 | try
36 | {
37 | screen = Convert.ToInt16(uri[2], CultureInfo.InvariantCulture);
38 | }
39 | catch { }
40 |
41 | if (screen < 0 || screen >= screens.Length)
42 | {
43 | screen = 0;
44 | }
45 | }
46 | return screen;
47 | }
48 |
49 | ///
50 | /// boilerplate HTML wraping for all the response streams
51 | ///
52 | ///
53 | ///
54 | internal static byte[] BuildHTML(string content)
55 | {
56 | return Encoding.UTF8.GetBytes("" + Environment.NewLine +
57 | "
Remote View" + Environment.NewLine +
58 | "" + Environment.NewLine +
59 | content +
60 | "" + Environment.NewLine +
61 | "