tag:blogger.com,1999:blog-78370360095769723772024-03-20T16:09:04.015+01:00Computer projects blog, by Johan DeckmarI'm a student going for a Master in Computer Science.
<br>
In this blog I will cover some of my projects in programming (C#/WPF/XNA, C++, Java) and other subjects.Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-7837036009576972377.post-13255286488180459442017-01-08T21:57:00.000+01:002017-01-10T21:04:56.256+01:00Docker containers with DNS and overlapping ports<div style="text-align: center;">
<br /></div>
<h2 style="text-align: center;">
<span style="font-size: x-large;">~ Problem </span>~</h2>
<div>
If we only have a few Docker containers on our local dev machine, then it is not too cumbersome to (re)use the domain-name "localhost" and ports 80/5432/3006/... </div>
<div>
<br /></div>
<div>
But when we start running several different projects' containers at the same time we quickly find ourselves juggling non-standard ports or stopping one project to start another.</div>
<div>
<br /></div>
<div>
This is because Docker, by default, will bind port-mappings to IP 0.0.0.0, which means listening on the given port on all network interfaces.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZYESSd0joV3VBXGaLLe9ok-o0LelF1J6HL4wMHX1-xo-JBhNgNg09_nXpery1610bo71km0g854oOUydJ9DV67BEbXhd4PRpiz1y0aj5YsFCnbiK7QNOyVqthytk-OyJeXGu8teDlgdo/s1600/external-0000.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZYESSd0joV3VBXGaLLe9ok-o0LelF1J6HL4wMHX1-xo-JBhNgNg09_nXpery1610bo71km0g854oOUydJ9DV67BEbXhd4PRpiz1y0aj5YsFCnbiK7QNOyVqthytk-OyJeXGu8teDlgdo/s1600/external-0000.png" /></a></div>
<div>
<br /></div>
<div>
This results in the computer not being able to re-use the same port for another application. I.e., if we are running a container mapped to 0.0.0.0:1234, then we cannot start another container on port 1234 (on any interface).</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguF67TZ5ukUdket4D1N7EvWNX0FGCOJXrR4yWmzE24mSZI_tll8p7JmFs77yNF9mIaThDRD6q8xCse69UV03eRSmhEYHgVPxwt6J6730hwVDMs1kmksTGdQuFpix7Fb9OuvZ5T46y1wQA/s1600/busy-0000.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguF67TZ5ukUdket4D1N7EvWNX0FGCOJXrR4yWmzE24mSZI_tll8p7JmFs77yNF9mIaThDRD6q8xCse69UV03eRSmhEYHgVPxwt6J6730hwVDMs1kmksTGdQuFpix7Fb9OuvZ5T46y1wQA/s1600/busy-0000.png" /></a></div>
<div>
<br /></div>
<h2 style="text-align: center;">
~ <span style="font-size: x-large;">Solution </span>~</h2>
<div style="text-align: left;">
We want to run many containers (web servers, databases, etc.) - and allow them to be mapped to the same ports. We also want to (optionally) assign domain names to our containers. We want a solution that works in any local application, with any ports/protocols, without configuring socks-proxy, port-forwarding or ssh-tunneling.</div>
<div>
<br /></div>
<h3>
Give each container (or project) it's own IP</h3>
<div>
The easiest way to allow for overlapping ports is to give each container port-mapping its own IP-address. But how many IP-addresses do you have pointing to your machine? Say hello to 127/8.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAR6U-SePcD8z_QjcwJYmoIE7dOHaha_fk2OrK-va1uhcuUfqQ28fBOxbsr02oCXx844EyT45QCTUGXAs9o7rG3aL54PqkP0wp8RCsmbaLXUrleVYWWBwd3dDLVWqFJx-mXcRWwbEGhu8/s1600/ping.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAR6U-SePcD8z_QjcwJYmoIE7dOHaha_fk2OrK-va1uhcuUfqQ28fBOxbsr02oCXx844EyT45QCTUGXAs9o7rG3aL54PqkP0wp8RCsmbaLXUrleVYWWBwd3dDLVWqFJx-mXcRWwbEGhu8/s1600/ping.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
In fact, all addresses from <b>127.0.0.1</b> to <b>127.255.255.254</b> point to your local machine.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, let's bind our port-mappings to a suiting local IP address. Docker allows up to do this by prefixing with the IP-address it should bind to on the host. The port syntax is the same in <i>docker run</i> and <i>docker-compose</i>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
In this example the address-space <b>127.10.x.x</b> is used for containers. Note that the same IP can be re-used as long as there are no overlapping ports. This is useful for a database + web database administration combo.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-_qcDYOPmRmpZt1vRGRjRrIZUQG1nqSYwvM4aGZhTA0B572we3L6N54AadJ8_Qt8CRbDs5rU2oWh1NIHtAIXlbVkBTNUYm3WkuGnH2LZg8M4yM7B0KH-SQgUlItUmbecDjrB7U-rst30/s1600/compose.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-_qcDYOPmRmpZt1vRGRjRrIZUQG1nqSYwvM4aGZhTA0B572we3L6N54AadJ8_Qt8CRbDs5rU2oWh1NIHtAIXlbVkBTNUYm3WkuGnH2LZg8M4yM7B0KH-SQgUlItUmbecDjrB7U-rst30/s320/compose.png" width="228" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3>
<br /></h3>
<h3>
Make a neat tree of domain names </h3>
<div>
Now since our containers have their own IP, we can start using DNS to access them in a human-friendly way. The easiest way is to make a sub-tree in a public DNS we control.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzcUZeRYWeKfK4NO1MLJKdQbLUtuIZgMLznNG0lsSh-TaLeS7zeuFjD-6KEL4BYRSXDU7fYLmy08eveM9CJrrNjksNvx6YLZHYw1y_vCBelH1a-KTDSKTBJHTBrnvf4N83ZVlcRcyBMfM/s1600/dns-tree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="129" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzcUZeRYWeKfK4NO1MLJKdQbLUtuIZgMLznNG0lsSh-TaLeS7zeuFjD-6KEL4BYRSXDU7fYLmy08eveM9CJrrNjksNvx6YLZHYw1y_vCBelH1a-KTDSKTBJHTBrnvf4N83ZVlcRcyBMfM/s320/dns-tree.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
As an alternative to buying/managing our public DNS (only ~ 20€/year, https://eurodns.com), we can instead use free wildcard DNS services like <b>nip.io</b> or <b>xip.io</b>. They respond with the IP provided in the domain-query.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRkoYXcBinJp4AgEr3Y33kGctTMVQ3pfJSC3Kmkaez1FCfpGlQXKEeMeCidPWV6ZneU51trKZbY1NEfo98YZ6l3rcmX9Ld0_R0PA5WSHynvgNFqb_IEqrxn51SVIY9Y6DuDqVYpc_iokE/s1600/xipnip.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRkoYXcBinJp4AgEr3Y33kGctTMVQ3pfJSC3Kmkaez1FCfpGlQXKEeMeCidPWV6ZneU51trKZbY1NEfo98YZ6l3rcmX9Ld0_R0PA5WSHynvgNFqb_IEqrxn51SVIY9Y6DuDqVYpc_iokE/s1600/xipnip.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Or, if we feel like taking the blue pill, we can run our own DNS in a container.</div>
<div class="separator" style="clear: both; text-align: left;">
http://www.damagehead.com/blog/2015/04/28/deploying-a-dns-server-using-docker/</div>
<div class="separator" style="clear: both; text-align: left;">
With this approach we can conjure a whole TLD for our containers, ex: <b>www.projectname.jode</b></div>
<div style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both; text-align: center;">
~ <span style="font-size: x-large;">Summary </span>~</h2>
<div class="separator" style="clear: both; text-align: left;">
This solution (tested on Windows and Linux) takes away port-mapping dilemmas and introduces the ability to use DNS. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
A few things to note:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ol>
<li>If any other application listens to 0.0.0.0:80, then it will not be possible to listen to ex. 127.10.2.1:80. A common gotcha is that Skype (Preferences > Advanced > Connection) does this, which can be disabled.</li>
<li>Using 127.x.x.x addresses only works locally. Even though the domain-names look very shareable, they are not.</li>
<li>To expand this pattern to work between multiple machines, the host needs to have a (virtual) interface for each external IP, and the network routing for the range needs to be set-up accordingly.</li>
</ol>
<br />
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com1tag:blogger.com,1999:blog-7837036009576972377.post-8255834732207740142014-10-19T15:52:00.002+02:002015-09-26T13:12:07.064+02:00Learn HTTPS by becoming your own CA<div>
<h2>
<span style="font-size: large;">Chain of trust</span></h2>
HTTPS depends on a chain of trust, and each step in the chain consists of a certificate that has been signed by its parent certificate. Usually the chain is 2~3 nodes long. The first node in the chain is one of around 50+ Certificate Authorities (CA) certificates configured to be trusted by your computer (and basically all computers world-wide). The last node in the chain is the certificate identifying the domain name of the HTTPS website you are visiting.<br />
<br />
Looking at https://www.google.se for example, the chain of trust starts from <i>GeoTrust Global CA</i>, which is already trusted by most computers by default. They then signed <i>Google Internet Authority G2</i>, and specifically allowing Google to sign other certificates on the behalf of GeoTrust. Google then signed a certificate with a Common Name (CN) of *.google.se, which matches the domain name(s) this certificate represents.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlBSaLABpJO6bp1J20_sA8hUqM0ePPyMaGZolitJNl3UPrwHvXdCcksLuBFa5QKQniO5vtGj7kz_JC0p8RcwoVamNdt91flt4kHOIiLOErj2SYbNIDE6BQUEkpKfXTHEDlpCHi0v84f68/s1600/chain.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlBSaLABpJO6bp1J20_sA8hUqM0ePPyMaGZolitJNl3UPrwHvXdCcksLuBFa5QKQniO5vtGj7kz_JC0p8RcwoVamNdt91flt4kHOIiLOErj2SYbNIDE6BQUEkpKfXTHEDlpCHi0v84f68/s1600/chain.png" /></a></div>
<br />
<h2>
<span style="font-size: large;">Certificate</span></h2>
</div>
A certificate is basically a public key, bundled with some key-values (like an expiration-date and, most importantly, a <i>Common Name</i>, CN), and appended with a hash of these things encrypted <b>with the private key that signed the certificate</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijZwDDMeKmruU4NTeD6BCUx0pAqWeHERY_1yMHoypNdg9ZjS1WpQT3VrEeAeQGvIW2s12aq8jGY2EY5gn2CF1Ru0dcUjKi3tiBja4ZiZcvoYpEiJ09i1dOY83P_9WpaiBPC1pNfHi97O4/s1600/cert.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijZwDDMeKmruU4NTeD6BCUx0pAqWeHERY_1yMHoypNdg9ZjS1WpQT3VrEeAeQGvIW2s12aq8jGY2EY5gn2CF1Ru0dcUjKi3tiBja4ZiZcvoYpEiJ09i1dOY83P_9WpaiBPC1pNfHi97O4/s1600/cert.png" width="320" /></a></div>
<br />
<br />
In many cases the Common Name in a certificate is the name of a company (like GeoTrust), but <b>for the website certificate (last-node in the chain) the CN must match the domain name</b> (as seen above for *.google.se, which is a wildcard match for www.google.se among others). Wildcard certificates are convenient since they can be reused for any domain names that matches.<br />
<br />
Each certificate has a corresponding private and public key.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHOY53l4JSX2Chhj3Radpq5bofmoIQSujHRIu6XWQUllzi1LBRN8TXBkYRZe1uerxjJZKjHpld2UL_TZi0jPS9BtnNkxaSrwsVb0rB2F_PVHRXu3gP4g2o-OYWduQjIpUVTR6e8FsreYM/s1600/certs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHOY53l4JSX2Chhj3Radpq5bofmoIQSujHRIu6XWQUllzi1LBRN8TXBkYRZe1uerxjJZKjHpld2UL_TZi0jPS9BtnNkxaSrwsVb0rB2F_PVHRXu3gP4g2o-OYWduQjIpUVTR6e8FsreYM/s1600/certs.png" width="400" /></a></div>
<br />
<br />
<h2>
<span style="font-size: large;">Certificate sign request (CSR)</span></h2>
Signing a certificate requires two peers (for example: <b>you</b> and <b>GeoTrust</b>) to co-operate. Each of the two peers has their own private key they need to keep secret. You want to send your public key and some key-values (such as the domain name in Common Name (CN)). To do this you create a <b>Certificate sign request (CSR)</b>, which is basically a certificate with a missing signature.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWqg8pZlw1AHmlSH0mQjA_JaohA1yfe8NTMrx9Ry0hdz040869glToEnBbg4XkmuEfYzsUbmmWqzlIL5NQitN2CUh1c-pITwEl4rpP2BzxDAxfvTT9avdwIx5L3MFegi_zzdmhwHGBxpo/s1600/sign_request.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="229" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWqg8pZlw1AHmlSH0mQjA_JaohA1yfe8NTMrx9Ry0hdz040869glToEnBbg4XkmuEfYzsUbmmWqzlIL5NQitN2CUh1c-pITwEl4rpP2BzxDAxfvTT9avdwIx5L3MFegi_zzdmhwHGBxpo/s1600/sign_request.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
When GeoTrust gets your CSR they can do some research to see that you actually own that domain name (usually by sending a verification e-mail to hostmaster@your-domain.com). They can also look up your company in a public directory and/or give you a phone call. When satisfied, they add some key-values such as <b>valid from</b>, <b>valid to</b> and <b>purpose</b> of certificate. (For example, the certificate <i>Google Internet Authority</i> has an extra purpose which gives it right to sign other certificates - but the <i>*.google.se</i> does not.) After adding their signature by (hashing and encrypting that hash with their private key) they send you back a complete certificate.<br />
<br />
<h2>
<span style="font-size: large;">Let's play Pretend Certificate Authority</span></h2>
First install OpenSSL and Nginx. Put openssl on path and open a terminal to the Nginx conf folder.<br />
<br />
<h3>
1.1) Generate your CA private RSA key (root.key)</h3>
<span style="font-size: x-small;">openssl genrsa -out root.key 2048</span><br />
<div>
<br /></div>
<div>
Here the key will be of size 2048 bits (default: 512). And the private key will not be password protected. (Password protection only benefits security if you have a password that can resist trillions of brute-force attempts per second, assuming you don't store it in plain-text in your server config which you probably would do anyway :).<br />
<div>
<br /></div>
<h3>
1.2) Generate your CA certificate sign request (root_req.csr)</h3>
<div>
<br /></div>
<div>
<span style="font-size: x-small;">openssl req -new -key root.key -out root_req.csr -sha256</span></div>
<div>
<br /></div>
<div>
You now need to fill in some info, but the most visible in the Common Name (CN).</div>
<div>
I wrote <b>Johan Deckmar</b> as my CA Common Name. After completing all the steps, this is what the browser will show:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHuJ0ax-jilJiN11B7zvJb8OaO7ZRldTBVrsiKp0EzaJsoYQFm8UA6L7QyrxCUepszD5d-f2wFIuqOu_Vr0eSgi4bXzrqOhoLUXOMqxgQSQoY__G6zCijdXX1Q7BZ2aM6aQ5tZGX3Epv4/s1600/my_ca_chain.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHuJ0ax-jilJiN11B7zvJb8OaO7ZRldTBVrsiKp0EzaJsoYQFm8UA6L7QyrxCUepszD5d-f2wFIuqOu_Vr0eSgi4bXzrqOhoLUXOMqxgQSQoY__G6zCijdXX1Q7BZ2aM6aQ5tZGX3Epv4/s1600/my_ca_chain.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">(Final result)</td></tr>
</tbody></table>
<div>
<br />
<h3>
1.3) Self-sign the root_req.csr with the root private key to get the CA root certificate (root.crt)</h3>
<span style="font-size: x-small;">openssl x509 -req -days 365 -in root_req.csr -signkey root.key -out root.crt -sha256</span><br />
<br />
Alright. Half way there, almost. Currently the root.key needs to be kept private. And the root.crt is a public certificate that you want people to trust as a root CA certificate. If you are doing this at your company, it's the root.crt that needs to be installed as a root CA cert on the employees computers.<br />
<br />
<b>Now, add the root.crt as a trusted CA root cert on your computer.</b><br />
<b><br />
</b> In Windows: Double-click on it --> Install certificate --> Next --> <b>Select destination:</b> Trusted root certificate authorities --> Next --> Complete.<br />
<br />
For managing certs in Windows in general: Start --> Run: certmgr.msc<br />
<br />
<h3>
2.1) Generate your web-server private RSA key (server.key)</h3>
<br />
<span style="font-size: x-small;">openssl genrsa -out server.key 2048</span><br />
<br />
<h3>
2.2) Generate your web-server certificate sign request (server_req.csr)</h3>
<br />
<span style="font-size: x-small;">openssl req -new -key server.key -out server_req.csr -sha256</span><br />
<br />
As before, fill in some info about your company and web-servrer. <b>NOTE: </b>Set the Common Name (CN) to a domain name (or wildcard) matching your webserver (where you have Nginx). If you are just trying this on your local computer, you can use the following DNS which points to your local IP-address: <b>localhost.deckmar.net</b><br />
<b><br />
</b> <br />
<h3>
2.3) Sign your web-server CSR with CA private key to make the cert (server.crt)</h3>
<br />
<span style="font-size: x-small;">openssl x509 -req -in server_req.csr -CA root.crt -CAkey root.key -set_serial 02 -out server.crt -days 365 -sha256</span><br />
<br />
<h3>
2.4) Concatenate your web-server cert and the root CA cert to form a chain (server.pem)</h3>
<br />
Soon when your web-server (Nginx) identifies itself with an HTTPS certificate, it should send the whole chain of certificates starting from the web-server cert and finishing with the root CA cert. This might sound complicated, but is actually done by concatinating the certificate files into one file like this:<br />
<br />
<span style="font-size: x-small;">cat server.crt root.crt > server.pem</span><br />
<br />
The file-ending doesn't actually matter, but I use the file name server.pem for a file with multiple certificates. (PEM is a format which can contain one or more certificates concatenated after each other).<br />
<br />
<h3>
3) Configure and start Nginx</h3>
<br />
Now open <b>conf/nginx.conf</b> and go down and un-comment the configurations under <b># HTTPS server</b>.<br />
<br />
I made the following three changes in nginx.conf:<br />
<br />
<span style="font-size: x-small;">ssl_certificate ../secure/server.pem;</span><br />
<span style="font-size: x-small;">ssl_certificate_key ../secure/server.key;</span><br />
<span style="font-size: x-small;"><br />
</span> <span style="font-size: x-small;">ssl_session_cache none;</span><br />
<br />
The path to the .pem and .key file is relative to the conf folder, so as you can see I put my keys and certs in a new folder called secure in the nginx folder.<br />
<br />
Start Nginx. Assuming everything was done correctly you should now get a green lock when you open:<br />
<a href="https://localhost.deckmar.net/">https://localhost.deckmar.net</a><br />
<br />
Since I used <i>mainframe.deckmar.net</i> as the domain name, this is what I see when inspecting the certificate on my server (click the green lock --> certificate information).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHuJ0ax-jilJiN11B7zvJb8OaO7ZRldTBVrsiKp0EzaJsoYQFm8UA6L7QyrxCUepszD5d-f2wFIuqOu_Vr0eSgi4bXzrqOhoLUXOMqxgQSQoY__G6zCijdXX1Q7BZ2aM6aQ5tZGX3Epv4/s1600/my_ca_chain.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHuJ0ax-jilJiN11B7zvJb8OaO7ZRldTBVrsiKp0EzaJsoYQFm8UA6L7QyrxCUepszD5d-f2wFIuqOu_Vr0eSgi4bXzrqOhoLUXOMqxgQSQoY__G6zCijdXX1Q7BZ2aM6aQ5tZGX3Epv4/s1600/my_ca_chain.png" /></a></div>
<br />
In some cases you need to restart your browser completely to use the latest certificate settings on your computer.<br />
<br />
Let me know how if goes if you try this out yourself. Especially if you find some mistake in the commands or something missing/wrong in the explanations.<br />
<br />
Cheers!</div>
</div>
Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com2tag:blogger.com,1999:blog-7837036009576972377.post-20158550790201788062012-08-05T19:35:00.000+02:002012-08-05T19:35:10.511+02:00One-keyboard-button compile your Google Drive-hosted Latex project<h2>
Context</h2>
<div>
First off, you already have your report on Google Drive and have made a compile-script, right? (See earlier post of how to set that up). </div>
<div>
<br /></div>
<h2>
Binding F2 to run the script</h2>
<div>
Let's say that "C:\thesis\build.bat" is the script that will download and compile your report. If we can bind one keyboard button to run that script (regardless of currently focused application) it could speed things up.</div>
<div>
<br /></div>
<div>
Here's how to beat Windows into running a .bat file by a key-press:</div>
<div>
<br /></div>
<div>
<ol>
<li>Right-click on "Cmd" in the start-menu and "Send to taskbar" (making a shortcut among the Windows 7 speed-launch-icons)</li>
<li>Shift-right-click the new cmd-icon in the taskbar and press Properties</li>
<li>In "target" box append: /C "C:\thesis\build.bat"<br />It should now say <i>%windir%\system32\cmd.exe /C "C:\thesis\\build.bat"</i> in the target-box. </li>
<li>In the keyboard-shortcut field select with mouse and press (for example) F2.</li>
<li>[Ok]</li>
</ol>
<div>
Now pressing F2 at any time brings up a console windows with your build-script flashing by like a black-and-white Matrix scene, and the disappears. This is great for typing in the Google Drive document and having your pdf open on the other monitor in <a href="http://blog.kowalczyk.info/software/sumatrapdf/download-free-pdf-viewer.html">SumatraPDF</a> which auto-refreshes the PDF when the file is updated.</div>
</div>
<div>
<br /></div>Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com1tag:blogger.com,1999:blog-7837036009576972377.post-42354393041270448122012-08-02T15:30:00.003+02:002012-08-02T15:30:31.932+02:00Auto-export URL references to Bibtex correctly in Medeley<h2>
The problem</h2>
<div>
Auto-exporting a bibtex file in Mendeley is nice and awsome when writing in Latex, but @misc URL references get their url in a \url tag, not in \howpublished{\url{...}} - which results in the URL not showing up in the References there when compiling the paper.</div>
<div>
<br /></div>
<h2>
Solution</h2>
<div>
In Tools - Options - Document Details - [Web page], check in "Medium" (this is mapped to \howpublished in the exported Bibtex). (Tips: check in Citation Key also to control the \cite key)</div>
<div>
<br /></div>
<div>
Now, in your URL references, write, for example, "Available: http://www.example...." in the "Medium" field in the details pane of your reference. Now the URL shows up correctly in your paper (and is clickable)!</div>
<div>
<br /></div>
<div>
<br /></div>Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com0tag:blogger.com,1999:blog-7837036009576972377.post-15343244550838077142012-03-08T15:50:00.002+01:002012-03-09T12:10:17.378+01:00Write LaTeX in Google Docs, compile locally to pdfI want to write my MS thesis in LaTeX code, but also from anywhere via Google Docs.<br />
<br />
This is how I automatically fetch and compile LaTeX code from Google Docs:<br />
<br />
<ol>
<li>Create the Google Docs document</li>
<li>Put some LaTeX code in it. Hopefully you have some "boilerplate" code you always start with.</li>
<li>(I assume you have a LaTeX compiler installed and know how to write in LaTeX)</li>
<li>Install <b>wget</b> if you don't have it (Windows:
<a href="http://gnuwin32.sourceforge.net/packages/wget.htm">http://gnuwin32.sourceforge.net/packages/wget.htm</a>, Other:
<a href="http://ftp.gnu.org/gnu/wget/">http://ftp.gnu.org/gnu/wget/</a>)</li>
<li>Press Share in your doc and allow anyone with the link to view it:<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYDv7EEP1FeZNWA0d3P6CivLjf5Cor-XdRo6UGsd7JX2ggELlUyEd8gXU51Onv5ywdb5SPW2feEZt2-hiiQYSLXyuBVSA_JxOFeKbxQeZTSgfi3xtjVABFN5aTHfKIbbZoLB1KRnpRwJk/s1600/thesis_google_doc_share_view.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYDv7EEP1FeZNWA0d3P6CivLjf5Cor-XdRo6UGsd7JX2ggELlUyEd8gXU51Onv5ywdb5SPW2feEZt2-hiiQYSLXyuBVSA_JxOFeKbxQeZTSgfi3xtjVABFN5aTHfKIbbZoLB1KRnpRwJk/s320/thesis_google_doc_share_view.png" width="320" /></a> </li>
<li>Save. Copy the public link. Change the "/edit" in the end to only "/export?format=txt".</li>
<li>Make a folder on your computer where you will be doing the LaTeX compilation.</li>
<li>Make a script which downloads the doc as raw text file and then compiles it with the latex compiler.</li>
</ol>
<br />
<div>
This is how my download-and-compile script looks like:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #fff2cc; font-family: 'Courier New', Courier, monospace; font-size: x-small;">"path/do/wget" "https://docs.google.com/doc..." -O thesis.tex --no-check-certificate</span></div>
<div>
<span style="background-color: #fff2cc; font-family: 'Courier New', Courier, monospace; font-size: x-small;">"path/to/pdflatex.exe" -interaction=nonstopmode "thesis.tex"</span></div>
</div>
<div>
<br /></div>
<div>
Those two lines are basically all it takes. When I run build_thesis.bat it downloads the very latest code and compiles it into a pdf.</div>
<br />
<b>Notes</b><br />
<ul>
<li>Problems with the UTF-8 BOM sneaking in to the beginning? Try using lualatex.exe instead which supports UTF-8.</li>
<li>If you want to split up into many .tex files you can make many docs and wget all of them.</li>
<li>If you use images it's easiest to simply have them in your working folder.</li>
<li>Images in the Google Doc will be ignored in the raw text, so you can have your images in the doc <i>and </i>the code for LaTeX to compile them in for a nice preview.</li>
<li>A ToC in the doc follow as text in raw format, so it's best not to use it and instead rely on scrolling.</li>
</ul>
<div>
Tell me your results. Happy LaTeXing!</div>
<div>
<br /></div>
<div>
/Johan</div>Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com3tag:blogger.com,1999:blog-7837036009576972377.post-20286313719338222602011-08-08T11:05:00.000+02:002011-08-08T11:05:19.303+02:00SSH med RSA-nycklar<span class="Apple-style-span" style="background-color: white; color: #222222; font-family: Muli, sans-serif;"></span><br />
<h2 style="font-family: 'Open Sans Condensed', sans-serif;">
Översikt</h2>
För att börja använda RSA-nycklar (istället för)/(tilsammans med) lösenord för SSH behöver du först göra två saker:<br />
<ol>
<li>Generera ett nyckel-par med PuTTYgen</li>
<li>Klistra in din publika nyckel på servern i <span class="Apple-style-span" style="color: black; font-family: monospace; white-space: pre;">$HOME/.ssh/authorized_keys</span></li>
<li><span class="Apple-style-span" style="color: black;"><span class="Apple-style-span" style="font-family: 'Times New Roman'; white-space: normal;">Lägg in din privata nyckel i PuTTY och spara anslutningen så du slipper göra om det </span></span></li>
</ol>
<h2 style="font-family: 'Open Sans Condensed', sans-serif;">
Guide för Windows</h2>
Se till att du har både <strong>PuTTY</strong> och <strong>PuTTYgen</strong>. <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">Ladda ner här</a>.<br />
Öppna <strong>PuTTYgen</strong> och generera ett nyckel-par med som är minst 1024 bitar.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1F5wlzNbka4_lLtAel2_cALTTYO9zZgOcNHISjHxPF4YGkPSedulXKqxMWv35OS2eztX6s75CbBdTCMXnaFkaVEWlu1IVr08DvMBrTHB9Q9k8DrWtzo5M7m16J-wRS4LeKMzvriKmEuw/s1600/puttygen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="309" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1F5wlzNbka4_lLtAel2_cALTTYO9zZgOcNHISjHxPF4YGkPSedulXKqxMWv35OS2eztX6s75CbBdTCMXnaFkaVEWlu1IVr08DvMBrTHB9Q9k8DrWtzo5M7m16J-wRS4LeKMzvriKmEuw/s320/puttygen.png" width="320" /></a></div>
<br />
<img src="file:///D:/Random.Bits/My%20Dropbox/Eclipse/Netcorner/NetcornerApp/assets/www/info/puttygen.png" />Lägg sedan ditt namn i kommentaren, t.ex "rsa-key-John", och (om du vill) ett lösenord som måste skrivas för att nyckeln ska kunna användas.<br />
<div class="infoBox" style="background-attachment: initial; background-clip: initial; background-color: #f1ea9b; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-color: rgb(212, 203, 109); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(212, 203, 109); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(212, 203, 109); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(212, 203, 109); border-top-style: solid; border-top-width: 1px; margin-bottom: 1em; margin-left: 1em; margin-right: 1em; margin-top: 1em; padding-bottom: 1em; padding-left: 1em; padding-right: 1em; padding-top: 1em;">
<em>Varför ha ett lösenord på nyckeln?</em><br />
<em><br /></em><br />
Om en hacker får tag på din privata nyckel måste han/hon först brute-force:a RSA-nyckelns lösenord för att kunna logga in på server. Det ger tid för en administratör att upptäcka läckan och blockera den/de läckta nycklarnas tillgång till servern.</div>
<img src="file:///D:/Random.Bits/My%20Dropbox/Eclipse/Netcorner/NetcornerApp/assets/www/info/puttygen2.png" /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTkQbuVn27eooPr_S6PXFpaBGyV4J7uWG_FIo_qED_OZhNiinXjEts88IAcfTiFccLTe7ONicZSHr98GA09hyphenhyphenGGl69tZrYYKSYivNI78FK4HdzTk-BC2qpxd9fyBnUIhL3rY6CANSfac/s1600/puttygen2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="309" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTkQbuVn27eooPr_S6PXFpaBGyV4J7uWG_FIo_qED_OZhNiinXjEts88IAcfTiFccLTe7ONicZSHr98GA09hyphenhyphenGGl69tZrYYKSYivNI78FK4HdzTk-BC2qpxd9fyBnUIhL3rY6CANSfac/s320/puttygen2.png" width="320" /></a></div>
<br />
Spara både den publika och privata nyckeln på din dator. <strong>All säkerhet hänger på att din privata nyckel hålls hemlig.</strong> Kopiera den text som är markerad i bildan ovanför. Det är din publika nyckel som du ska lägga in på servern.<br />
<div class="infoBox" style="background-attachment: initial; background-clip: initial; background-color: #f1ea9b; background-image: initial; background-origin: initial; border-bottom-color: rgb(212, 203, 109); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(212, 203, 109); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(212, 203, 109); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(212, 203, 109); border-top-style: solid; border-top-width: 1px; margin-bottom: 1em; margin-left: 1em; margin-right: 1em; margin-top: 1em; padding-bottom: 1em; padding-left: 1em; padding-right: 1em; padding-top: 1em;">
<em>Hantering av din privata nyckel.</em><br />
<em><br /></em><br />
Några riktlinjer:<ul>
<li>Lägg inte nyckeln i Dropbox</li>
<li>Skicka inte nyckeln i e-post</li>
<li>Ge inte din nyckel till någon annan - generera istället en ny</li>
<li>Använd ett USB-minne om du behöver flytta en privat nyckel</li>
<li>Vill du ha en nyckel hemma också? Generera en ny och maila den <em>publika</em> nyckeln så du kan lägga in den från kontoret</li>
</ul>
</div>
<br />
Sista steget: Kopiera din publika nyckel som står i rutan "Public key for pasting into..", och klistra in den i <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">$HOME/.ssh/authorized_keys</span> på en egen rad.<br />
<br />
Lägg in din privata nyckel i PuTTY och spara anslutningen i Session så du slipper göra om det.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_MQ29WQjoGLcXkEJZvzYMAzVScz-kciLgvEDBBbZBnt49jUJDqKc_3ayOjksYYS1J95suSdRBQfkDCQdihyrF0UnjLZzc_cHzS4fBTMXC-0BkqAwyX9ct-8VJnEHKJq9OBuusRtqHtlY/s1600/puttygen3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_MQ29WQjoGLcXkEJZvzYMAzVScz-kciLgvEDBBbZBnt49jUJDqKc_3ayOjksYYS1J95suSdRBQfkDCQdihyrF0UnjLZzc_cHzS4fBTMXC-0BkqAwyX9ct-8VJnEHKJq9OBuusRtqHtlY/s320/puttygen3.png" width="320" /></a></div>
<span class="Apple-style-span" style="font-family: monospace;"><span class="Apple-style-span" style="white-space: pre;"><br /></span></span><br />
Det anses vara helt säkert att ha en publik SSH-server som endast accepterar RSA-nyckel-inloggning - förutsatt att du håller dina privata nycklar privata. Därför bör du definitivt <b>stänga av lösenords-inloggning i /etc/ssh/sshd_config</b> så att alla brute-force attacker blir meningslösa.<br />Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com0tag:blogger.com,1999:blog-7837036009576972377.post-68935279397743801742010-11-07T17:58:00.005+01:002010-11-08T08:17:18.493+01:00My opinion on the future structure of the web<p>With XHTML Strict we have separated content and design. Using CSS we have been able to remove much redundancy in the code delivered to browsers. We basically define snippets of design and apply them on an arbitrary amount of elements.</p>
<p>I believe the next step is to separate data and structure, by defining snippets of structure and applying to on arbitrary amount of data.</p>
<p>This can be easily achieved now using <a href="http://api.jquery.com/category/plugins/templates/">jQuery Templates</a>, which at the time of writing is in beta.</p>
<h2>Example:</h2>
<p>Imagine the comment-section on YouTube or this blog. Each comment might have an image, a timestamp, username, thumbs-up/down and some wrapping. All this XHTML code is repeated for every comment. </p>
<h3>A short comment</h3>
<p>Using a short YouTube comment as an example, the XHTML code consists of 721 bytes of data (which has been generated in a loop on the server side and transmitted to the browser). Removing all XHTML code from the example comment - leaving only the actual information needed - yields 48 bytes of data. In other words: The XHTML code <strong>contained 6.657% information, the rest being redundant structure code which is repeated for each comment.</strong></p>
<h4>Visual representation:</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUzOHIxFaNN1u1guBQz3peR4uDTmqgXaHZURmn8YrKPiOerMzSN_sLJOZw1aTK2iLN1RtTf4ppr5RFu8tXHJXVHIUCuAwK3ldozbFrWugU8pIEgGVGekUnr4Yq7S1hLjR9GpwOU0_lLxg/s1600/yt_comment_short.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="37" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUzOHIxFaNN1u1guBQz3peR4uDTmqgXaHZURmn8YrKPiOerMzSN_sLJOZw1aTK2iLN1RtTf4ppr5RFu8tXHJXVHIUCuAwK3ldozbFrWugU8pIEgGVGekUnr4Yq7S1hLjR9GpwOU0_lLxg/s400/yt_comment_short.png"></img></a></div>
<h4>Code of the short comment:</h4>
<p><li data-author-viewing="False" data-id="5mm3YzP7OX3U298MLeHm0HolNSkstTdEdfbrhWTEAnI" data-score="0" data-author="SuperWizTech" data-pending="0" data-blocked="False" data-flagged="False" data-removed="False" class="comment current">
<div class="metadata">
<div>
<a class="author" href="/user/SuperWizTech" title="SuperWizTech">SuperWizTech</a>
</div>
<div>
<span class="time">4 months ago</span>
</div>
</div>
<div class="content">
<div class="comment-text" dir="ltr">
<p>completly awsome? :D</p>
</div>
<div class="metadata-inline">
<a class="author" href="/user/SuperWizTech">SuperWizTech</a>
<span class="time">4 months ago</span>
</div>
</div>
</li></p>
<h3>A long comment</h3>
<p>The same comparison on a (relatively) long comment yields an information-to-structure-code-ratio of 453 / 1518 = 29.84%</p>
<h4>Visual representation</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK96YVqgp63XUVpDt8dtjAVnEavQuD9hG5wVNS2NBrf63aYccohhe9jutIuIAgEli8ccEoRuKIaiMCbJ-9OLUuyVlmFkXyOAbI-5qDYDCgHGrett1ALA9A23lr2wAupGkJJRnihJrP96Y/s1600/yt_comment_long.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="95" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK96YVqgp63XUVpDt8dtjAVnEavQuD9hG5wVNS2NBrf63aYccohhe9jutIuIAgEli8ccEoRuKIaiMCbJ-9OLUuyVlmFkXyOAbI-5qDYDCgHGrett1ALA9A23lr2wAupGkJJRnihJrP96Y/s400/yt_comment_long.png"></img></a></div>
<h4>Code of a long comment</h4>
<p><li data-author-viewing="False" data-id="5mm3YzP7OX2-iXk_QNRtPTEnt5jOC_kWffObtTXjW24" data-score="4" data-author="jpsieben7" data-pending="0" data-blocked="False" data-flagged="False" data-removed="False" class="comment current">
<div class="metadata">
<div>
<a class="author" href="/user/jpsieben7" title="jpsieben7">jpsieben7</a>
</div>
<div>
<span class="time">2 years ago</span>
<span class="comments-rating-positive">4 <img class="master-sprite comments-rating-thumbs-up" src="http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif"></span>
</div>
</div>
<div class="content">
<div class="comment-text" dir="ltr">
<p>what you could do is get a rechargeable battery pack and 2 nxts. then have the base hooked up to the wall so it automatically keeps charging and then have the base use the light sensore and send out a strobe which the bartender finds and? goes and gets. a little bit more complicated but would be a bit more acurate and quick. also make the base have a gravity fed drink loader in it so when 1 is taken another takes its place.</p>
</div>
<div class="metadata-inline">
<a class="author" href="/user/jpsieben7">jpsieben7</a>
<span class="time">2 years ago</span>
<span class="comments-rating-positive">4 <img class="master-sprite comments-rating-thumbs-up" src="http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif"></span>
</div>
</div>
</li></p>
<h2>Summary</h2>
<p>Assuming (educated guesses):</p>
<ul>
<li>Average comment text size: 200 bytes (justified for some Unicode encoding)</li>
<li>Additional unique data per comment: 50 bytes (such as: index; special class-names)</li>
<li>Data structure overhead per comment: 30 bytes (using JSON)</li>
</ul>
<p>If we were able to represent the data (username, comment-text and timestamp) with said overhead and have its structure defined only once, the comment section on <strong>YouTube would only use less than 25% (280 / 1265 = 22.134% in this example) of it's current bandwidth <em>for the comment section</em> for each [page view]/[comment page-flip].</strong></p>
<p>Simply put, separating structure from data on the web would first of all reduce many chunks of redundant code in repetitive sections (such as in comments- and search-result-sections). Secondly the data would - by design - be set free from their client-specific (in this case client = web-browser) delivery.</p>
<p>One benefit from such a separation would be the possibility of easily creating a completely different interaction to the internet service on a mobile client, without the need of making a new API for this.</p>Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com0tag:blogger.com,1999:blog-7837036009576972377.post-22476874989954681342009-09-13T12:52:00.031+02:002010-02-01T15:39:26.382+01:00"Spotify Friends" Part 2<span style="font-size: x-large;">Part 2. Controlling Spotify playback by injecting keyboard messages</span><br />
<br />
As we disscussed in <a href="http://johan.deckmar.net/2009/09/c-wpf-project-spotify-friends.html">Part 1</a>, a Windows application has a WndProc that receives messages such as WM_KEYDOWN from the operating system when the user interacts with the window. Now we want to send those messages ourselves to simulate the user pressing shortcuts (such as [space] for play/pause).<br />
<br />
We first prepare by spying on the Spotify window with Spy++ (a tool that comes with Microsoft Visual Studio). Attach to Spotify using Spy++ and filter out just the keyboard messages. Now when you press the shortcut keys in Spotify you will see exactly what messages were sent from the OS. This happens when we press [space]:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilKuR-IJHmbFqRuo7T9c2UNUy0iXsv92HrrZOMtv-7k2z3IH4odaftvHhsds38hYj71oniBVOZAzIJNw2AizRIhjf02XsJ65nddGtS2UdjQP4a1DO3KS2Bblm42_DQ-U4-0OnBS4x_b-0/s1600-h/130909-screen-Spotify-SpyPlusPlus.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilKuR-IJHmbFqRuo7T9c2UNUy0iXsv92HrrZOMtv-7k2z3IH4odaftvHhsds38hYj71oniBVOZAzIJNw2AizRIhjf02XsJ65nddGtS2UdjQP4a1DO3KS2Bblm42_DQ-U4-0OnBS4x_b-0/s320/130909-screen-Spotify-SpyPlusPlus.png" /></a></div>
<br />
<br />
To send our own [space] message we do the following:<br />
<ul>
<li>Find the Handle of the Spotify window</li>
<li>Send the message using PostMessage( .. ) in user32.dll</li>
</ul>
<b>Finding the Handle (and getting current song) of the Spotify window in C#</b><br />
<br />
We now search for all processes called Spotify. When we find the right process we can get both the handle we are looking for and the title of the main window - which shows what song (if any) is currently playing. If we cannot find the process then we assume Spotify is not running.<br />
<br />
<pre class="csharp" name="code">spotifyWindow = 0;
Process[] processes = Process.GetProcessesByName("Spotify");
foreach (Process proc in processes)
{
if (!proc.MainModule.FileName.EndsWith("spotify.exe")) continue;
if (proc.MainWindowTitle.Length >= 10)
{
NowPlaying = proc.MainWindowTitle.Substring(10);
SpotifyStatus = AppStatus.Playing;
}
else
{
NowPlaying = "";
SpotifyStatus = AppStatus.Paused;
}
spotifyWindow = (int)proc.MainWindowHandle;
}
if (spotifyWindow == (int)IntPtr.Zero)
SpotifyStatus = AppStatus.NotRunning;
</pre>
<span style="font-family: -webkit-monospace; font-size: small;"><span style="font-size: 13px;"><br /></span></span><br />
<b>Sending messages to the Spotify window</b><br />
<br />
Sending [space] press is just a matter of copycatting the messages we saw in Spy++. But first we need to import the PostMessage( .. ) from user32.dll.<br />
<pre class="csharp" name="code">[DllImport("USER32.DLL")]
static extern int PostMessage(
int hwnd,
int msg,
int character,
uint count);</code>
</pre>
<br />
<br />
If you are in a WPF project this is a good time to - like I said at the end of Part 1 - add a reference to System.Windows.Forms and add:<br />
<span class="Apple-style-span" style="font-family: monospace;"></span><br />
<pre class="csharp" name="code">using FormsNS = System.Windows.Forms</pre>
<br />
<span class="Apple-style-span" style="font-family: monospace;"><span class="Apple-style-span" style="font-family: "Times New Roman";">If you have a Form application you just use Keys directly. To send [space] we do this:</span></span><br />
<pre class="csharp" name="code">const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
if (spotifyWindow != 0)
{
PostMessage(spotifyWindow, WM_KEYDOWN, (int)FormsNS.Keys.Space, 1);
Thread.Sleep(100);
PostMessage(spotifyWindow, WM_KEYUP, (int)FormsNS.Keys.Space, 1);
}</pre>
<br />
This time we get away with putting any integer as the last argument in PostMessage, but we will have to be more precise later on when we are sending the more complex shortcuts (like Ctrl+Right).<br />
<br />
<b>Sending Ctrl + Key to Spotify</b><br />
<br />
If we look in Spy++ it seems like we can get away with simulating both the [ctrl] and the [right] key at the same time, but that will not work. My theory is that when Spotify gets the [right] key it will look at the keyboard to see if [ctrl] is pressed (because this is easier to do). Our messages so far will not fool Spotify if it looks at the state of the keyboard - so we now need to choose one out of two solutions:<br />
<ol>
<li>Force ourselves to use [ctrl] + [any other keys] in our global hot-key combo (Spotify will see that [ctrl] is pressed when we send [right] for example)<br /><br />or</li>
<li>Use other key combos, and fake that [ctrl] is pressed</li>
</ol>
<div>
If you are satisfied with choice 1 you just need to send the [right] (etc.) keys correctly and you are done. For that reason we will first look at how we send those keys, then look at how we can spoof the [ctrl] key.</div>
<div>
</div>
<div>
<b><br /></b><br />
<b>Sending [up], [down], [left] or [right]</b></div>
<div>
</div>
<div>
<br />
This time we need to get the last argument in PostMessage correct. We press [ctrl] + [right] in Spotify while spying with Spy++. Then we right-click and look at the Properties on the WM_KEYDOWN message that has VK_RIGHT in it (should be the second one if you cleared the log). In Properties we first see wParam which is the code for the key - (int)FormNS.Keys.Right in this example. We also see the lParam which we need to send as the last argument in PostMessage.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlB_Ql3WHu09hhIejrE7OXvk-rX5jiwg3R_RLoJKf4JETdXf4q2-3WvEZQ1t4ZOzqyQxd1oXQVwo0KD1DwarUKoo1HbtoWg_NQ5MGP8-ZywBxrW0pyFBYxMQebEWsubXOD9xjs0mqWWwM/s1600-h/130909-screen-Spotify-SpyPlusPlus-lParam.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlB_Ql3WHu09hhIejrE7OXvk-rX5jiwg3R_RLoJKf4JETdXf4q2-3WvEZQ1t4ZOzqyQxd1oXQVwo0KD1DwarUKoo1HbtoWg_NQ5MGP8-ZywBxrW0pyFBYxMQebEWsubXOD9xjs0mqWWwM/s320/130909-screen-Spotify-SpyPlusPlus-lParam.png" /></a></div>
<br />
But I have already done that work for you. Here you go:<br />
<pre class="csharp" name="code">
PostMessage(spotifyWindow, WM_KEYDOWN, (int)FormsNS.Keys.Right, 0x014D0001);
PostMessage(spotifyWindow, WM_KEYUP, (int)FormsNS.Keys.Right, 0xC14D0001);
PostMessage(spotifyWindow, WM_KEYDOWN, (int)FormsNS.Keys.Left, 0x014B0001);
PostMessage(spotifyWindow, WM_KEYUP, (int)FormsNS.Keys.Left, 0xC14B0001);
PostMessage(spotifyWindow, WM_KEYDOWN, (int)FormsNS.Keys.Up, 0x01480001);
PostMessage(spotifyWindow, WM_KEYUP, (int)FormsNS.Keys.Up, 0xC1480001);
PostMessage(spotifyWindow, WM_KEYDOWN, (int)FormsNS.Keys.Down, 0x01500001);
PostMessage(spotifyWindow, WM_KEYUP, (int)FormsNS.Keys.Down, 0xC1500001);
</pre>
</div>
<div>
<pre></pre>
<div>
<b><br /></b><br />
<b>NOTE:</b> Put in a Thread.Sleep(100) between each key you send. I guess the application will not react if the keys are pressed for an extremely short timespan.</div>
<div>
</div>
<div>
If you choose to have [ctrl] in your global hot-keys you now know all you need to know to control Spotify's playback, volume and get the currently playing song.</div>
<div>
</div>
</div>
<b><br /></b><br />
<b>Faking the [ctrl] key being pressed</b><br />
<br />
To set the [ctrl] key as down or up we need to import the following method in user32.dll:<br />
<pre class="csharp" name="code">[DllImport("user32.dll", EntryPoint = "keybd_event", CharSet = CharSet.Auto, ExactSpelling = true)]
static extern void keybd_event(byte vk, byte scan, int flags, int extrainfo);</pre>
<br />
To press down we pull this one-liner:<br />
<pre class="csharp" name="code">keybd_event((byte)FormsNS.Keys.ControlKey, 0x1D, 1, 0);</pre>
<br />
<br />
And to release [ctrl]:<br />
<pre class="csharp" name="code">keybd_event((byte)FormsNS.Keys.ControlKey, 0x1D, 1 | 2, 0);</pre>
<br />
Using these you can now have global hot-keys such as [alt] + [up] (volume up) and [alt] + [right] (next song). When Spotify checks to see the status of the [ctrl] key it will see it as being pressed.<br />
<br />
<span style="font-size: x-large;">Summary</span><br />
<br />
Looking back we can sum up what we need to do to send key-presses to another window:<br />
<ul>
<li>Get the Handle of the window. The Handle is used by the Windows GUI manager to refer to uniquely identify windows (and other controls).</li>
<li>Send the correct messages via PostMessage. Note that the last argument might be important. In that case we can easily get it with Spy++.</li>
<li>If we do not want to hold down [ctrl], but we want the application to think [ctrl] is being held down, then we probably need to use keyd_event( .. ) to set [ctrl]</li>
</ul>Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com4tag:blogger.com,1999:blog-7837036009576972377.post-47801872600866125452009-09-12T14:11:00.135+02:002009-09-13T09:05:44.828+02:00C# / WPF project: "Spotify Friends" Part 1<div style="text-align: left;">
<span style="font-family: verdana;"><span style="font-size: small;">Let's kick it off with a mixture of C# with WPF and (kind of) C++.</span></span></div>
<div style="text-align: left;">
<span style="font-family: verdana;"><span style="font-size: small;">
</span> </span></div>
<div>
<span style="font-family: verdana;"><span style="font-size: small;">I'll start by saying; this project is in no way associated with or endorsed by the amazingly great music service Spotify. This project has no intent of misusing the Spotify trademark or in any other way step on anyones to</span></span><span style="font-size: small;"><span style="font-family: verdana;"></span></span><span style="font-family: verdana;"><span style="font-size: small;">es. "Spotify Friends" is just an internal code-name.</span></span><br />
<span style="font-family: verdana;"><br /></span></div>
<div>
<span style="font-family: Arial;"><span style="font-size: x-large;">Overview</span></span></div>
<div>
<span style="font-family: verdana;"><span style="font-size: small;">
</span> </span></div>
<div>
<span style="font-family: verdana;"><br /></span><br />
<span style="font-family: verdana;">"Spotify Friends" is a [client(s) --> server] project that lets users see what their friends are listening to at the moment. The client also adds the functionallity of controlling the playback with global hot-keys; changing the song or volume while playing games or surfing - without opening the Spotify window.</span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH2j-TC_lbaLXtKljso2QEZqAnfQbQ9v3JneL5FIXq_M7_akbysS4w6idLx_KvHKzmnFz55lpB8e59pVOR9hy1Pg2uMBwx2d_sQ0Eh8ksWA_V_BG7_0C-s5XDmh2eUz-IGzzbKgOsZNqk/s1600/120909-screen-SpotFriends_client.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5380547118207808050" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH2j-TC_lbaLXtKljso2QEZqAnfQbQ9v3JneL5FIXq_M7_akbysS4w6idLx_KvHKzmnFz55lpB8e59pVOR9hy1Pg2uMBwx2d_sQ0Eh8ksWA_V_BG7_0C-s5XDmh2eUz-IGzzbKgOsZNqk/s320/120909-screen-SpotFriends_client.png" style="display: inline; height: 320px; margin-top: 0px; text-align: right; width: 170px;" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu3hyphenhyphengDT6T0GY3N7RuL3iU7MggXSawyY33WmpCT666GKU47KtG3_0sv0sSgDSee0x9YiVmYWngkMFWY3_MexldM1N9RIwyzrv91N8QBNMs_QWhAE1romJ7aPAo-uegumqHrBjGzp5EzG0/s1600/120909-screen-SpotFriends_server.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-size: small;"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5380547340863002978" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu3hyphenhyphengDT6T0GY3N7RuL3iU7MggXSawyY33WmpCT666GKU47KtG3_0sv0sSgDSee0x9YiVmYWngkMFWY3_MexldM1N9RIwyzrv91N8QBNMs_QWhAE1romJ7aPAo-uegumqHrBjGzp5EzG0/s320/120909-screen-SpotFriends_server.png" style="display: inline; margin-top: 0px; text-align: left;" /></span></a></div>
<span style="font-family: verdana;"><span style="font-size: small;">
</span> </span></div>
<div>
<span style="font-family: verdana;"><span style="font-family: Georgia;"><span style="font-size: small;"> </span></span></span></div>
<div>
<span style="font-family: Arial;"><span style="font-size: 32px;"><br /></span></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size: x-large;">Part 1. Global keyboard hooking in C# Forms and WPF</span></span><br />
<span style="font-family: Arial;"><b><br /></b></span><br />
<span style="font-family: Arial;"><b><span style="font-size: small;">H</span></b><b><span style="font-size: small;">o</span></b><b><span style="font-size: small;">w</span></b><b><span style="font-size: small;"> </span></b><b><span style="font-size: small;">i</span></b><b><span style="font-size: small;">t</span></b><b><span style="font-size: small;">'</span></b><b><span style="font-size: small;">s</span></b><b><span style="font-size: small;"> </span></b><b><span style="font-size: small;">d</span></b><b><span style="font-size: small;">o</span></b><b><span style="font-size: small;">n</span></b><b><span style="font-size: small;">e</span></b><b><span style="font-size: small;"> </span></b><b><span style="font-size: small;">i</span></b><b><span style="font-size: small;">n</span></b><b><span style="font-size: small;"> </span></b><b><span style="font-size: small;">C</span></b><b><span style="font-size: small;">+</span></b><b><span style="font-size: small;">+</span></b></span>
<span style="font-family: Arial;"><b>
</b></span></div>
<div>
<span style="font-family: verdana;"> </span></div>
<div>
<span style="font-family: verdana;"><br /></span><br />
<span style="font-family: verdana;"><span style="font-size: small;">If we were to make a Windows GUI application in C++, we would have a method in our GUI-class called WndProc which would receive messages from the operating system, such as WM_KEYDOWN or WM_LBUTTONDOWN (left button down). The WM_KEYDOWN message will only come to us when the user pushes a button and our window is the currently active one, so we can't rely on that one for our global hot-keying. Luckily the people a Microsoft created just what we need; a method in user32.dll called RegisterHotKey( .. ) that allows us to ask the OS: </span></span>
<span style="font-family: verdana;"><span style="font-size: small;">
</span> </span>
<span style="font-family: verdana;"><span style="font-size: small;">"Can you please notify me any time the user presses Alt + Z? :)". </span></span>
<span style="font-family: verdana;"><span style="font-size: small;">
</span> </span>
<span style="font-family: verdana;"><span style="font-size: small;">If no other application has been granted that combination, the OS will gladly say yes. So from now on when the user presses Alt + Z, our WndProc will receive a message called WM_HOTKEY and parameters explaining which key combi<span style="font-family: Verdana, sans-serif;">nation was pressed.</span></span></span><br />
<span style="font-family: Verdana;"><b><br /></b></span><br />
<span style="font-size: small;"><span style="font-family: Verdana, sans-serif;">
<b>Registering for hot-keys in C#</b></span></span><br />
<span style="font-family: Verdana;"><br /></span><br />
<span style="font-family: Verdana, sans-serif;">
</span>
<span style="font-family: verdana;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';"><span style="font-family: verdana;"><span style="font-family: Verdana, sans-serif;">We ne</span>ed to run the RegisterHotKey method in user32.dll. To get access to this method we import it like this:</span></span></span></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"><div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span style="font-family: verdana;"><span style="font-size: small;"><span style="font-family: Verdana;"></span></span></span></div>
<span style="font-family: verdana;"></span>
<span style="font-family: verdana;"></span>
<span style="font-family: verdana;"></span>
<span style="font-family: verdana;"></span>
<span style="font-family: verdana;"></span>
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"><pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="color: green;"><span style="font-size: small;">// Register a hot key with Windows</span></span><span style="font-size: small;">
[<span style="color: #3d85c6;">DllImport</span>(</span><span style="color: #006080;"><span style="font-size: small;">"user32.dll"</span></span><span style="font-size: small;">)]
</span><span style="color: blue;"><span style="font-size: small;">private</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">static</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">extern</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">bool</span></span><span style="font-size: small;"> RegisterHotKey(</span><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">windowHandle, </span><span style="color: blue;"><span style="font-size: small;">int</span></span><span style="font-size: small;"> id, </span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;"> modifiers, </span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;"> virtualKey);
</span><span style="color: green;"><span style="font-size: small;">// Unregister a certain hot key with Windows</span></span><span style="font-size: small;">
[<span style="color: #3d85c6;">DllImport</span>(</span><span style="color: #006080;"><span style="font-size: small;">"user32.dll"</span></span><span style="font-size: small;">)]
</span><span style="color: blue;"><span style="font-size: small;">private</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">static</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">extern</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">bool</span></span><span style="font-size: small;"> UnregisterHotKey(</span><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">windowHandle, </span><span style="color: blue;"><span style="font-size: small;">int</span></span><span style="font-size: small;"> id);</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">
</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black;"><span style="font-family: Verdana;"><span style="white-space: normal;"><span style="font-size: small;">
</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black;"><span style="white-space: normal;"><span style="font-family: Verdana, sans-serif;"><span style="font-size: small;">To register a hot-key we must have a handle to our window.</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black;"><span style="white-space: normal;"><span style="font-family: Verdana, sans-serif;"><span style="font-size: small;">
</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black;"><span style="white-space: normal;"><span style="font-family: Verdana, sans-serif;"><span style="font-size: small;">Getting the Handle to our window in a Windows.Form application:</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black;"><span style="font-family: Verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">handle = </span><span style="color: blue;"><span style="font-size: small;">this</span></span><span style="font-size: small;">.Handle;</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">
</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana;"><span style="white-space: normal;">
<br />
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">Getting the Handle to our window in a WPF application:</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;"><span style="font-family: Consolas; font-size: 13px; white-space: pre;"><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">handle = </span><span style="color: blue;"><span style="font-size: small;">new</span></span><span style="font-size: small;"> WindowInteropHelper(</span><span style="color: blue;"><span style="font-size: small;">this</span></span><span style="font-size: small;">).Handle;</span></span></span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-size: medium;"><span style="font-size: 16px;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;"><span style="font-family: Consolas; font-size: 13px; white-space: pre;"><span style="font-size: small;"><span style="font-family: verdana; white-space: normal;">Now when we have the handle we can register a hot-key when our window has loaded. The id we use when registering is used later for unregistering. Here is a simple example of registering:</span></span></span></span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;"><span style="font-family: Consolas; font-size: 13px; white-space: pre;"><span style="font-size: small;"><span style="font-family: verdana; white-space: normal;"><span style="color: green; font-family: Consolas; font-size: 13px; white-space: pre;">// Register a hot key</span></span></span></span></span></span></span></pre>
<pre class="csharpcode" style="background-color: white; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-family: Verdana;"><pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana; white-space: normal;"><pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-family: Verdana;">
<br />
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="color: blue;"><span style="font-size: small;">if</span></span><span style="font-size: small;"> (!RegisterHotKey(handle, 1, (</span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;">) (</span><span style="color: #3d85c6;"><span style="font-size: small;">ModifierKeys</span></span><span style="font-size: small;">.Alt | </span><span style="color: #3d85c6;"><span style="font-size: small;">ModifierKeys</span></span><span style="font-size: small;">.Control), (</span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;">) </span><span style="color: #006080;"><span style="font-size: small;">'P'</span></span><span style="font-size: small;">))
</span><span style="color: blue;"><span style="font-size: small;">throw</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">new</span></span><span style="font-size: small;"> InvalidOperationException(</span><span style="color: #006080;"><span style="font-size: small;">"Could not register the hot key"</span></span><span style="font-size: small;">);</span></pre>
</span></span></span></pre>
</span></pre>
</span></span></span></pre>
</span></span></pre>
</span></div>
</span></div>
<div>
<span style="font-family: verdana;"><b><span style="font-size: small;">
</span> </b><span style="font-size: small;"> </span></span></div>
<div>
<span style="font-family: verdana;"><b><br /></b></span><br />
<span style="font-family: verdana;"><b><span style="font-size: small;">Listening to messages in a Windows.Form application</span></b></span></div>
<div>
<span style="font-family: verdana;"><b><span style="font-size: small;">
</span> </b><span style="font-size: small;"> </span></span></div>
<div>
<span style="font-family: verdana;"><br /></span><br />
<span style="font-family: verdana;"><span style="font-size: small;">In C# we can create a Windows.Forms application. This is the old school way of creating a GUI application, which was the only way back in the days of .NET 2.x. In a Form class we can override the WndProc and get direct access to the messages that the OS is sending to our window. We can now listen to the WM_HOTKEY message and react accordingly.</span></span></div>
<div>
<span style="font-family: verdana;"><span style="font-size: small;">
</span> </span></div>
<div>
</div>
<span style="font-family: verdana;"><b><br /></b></span><br />
<span style="font-family: verdana;"><b><span style="font-size: small;">Alright, how is this done in WPF?</span></b></span><br />
<span style="font-family: verdana;"><br /></span><br />
<span style="font-family: verdana;"><b><span style="font-size: small;">
</span> </b></span>
<span style="font-family: verdana;"><span style="font-size: small;">WPF is very different from Windows.Form and doesn't have a WndProc method. But we will make our own. Let's call it WndProc.</span></span><br />
<span style="font-family: verdana;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';"></span></span></span><br />
<span style="font-family: verdana;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';"></span></span></span><br />
<span style="font-family: verdana;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';"></span></span></span><br />
<span style="font-family: verdana;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';"><pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="color: blue;"><span style="font-size: small;">const </span></span><span style="color: blue;"><span style="font-size: small;">int</span></span><span style="font-size: small;"> WM_HOTKEY = 0x0312;</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></pre>
</span></span></span>
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"></span><br />
<span style="font-family: verdana;"><pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="color: blue;"><span style="font-size: small;">public</span></span><span style="font-size: small;"> IntPtr WndProc(</span><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">hwnd, </span><span style="color: blue;"><span style="font-size: small;">int</span></span><span style="font-size: small;"> msg, </span><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">wParam, </span><span style="color: #3d85c6;"><span style="font-size: small;">IntPtr </span></span><span style="font-size: small;">lParam, </span><span style="color: blue;"><span style="font-size: small;">ref</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">bool</span></span><span style="font-size: small;"> handled)
{
</span><span style="color: green;"><span style="font-size: small;">// check if we got a hot key pressed.</span></span><span style="font-size: small;">
</span><span style="color: blue;"><span style="font-size: small;">if</span></span><span style="font-size: small;"> (msg == WM_HOTKEY)
{
</span><span style="color: green;"><span style="font-size: small;">// get the keys.</span></span><span style="font-size: small;">
</span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;"> key = (</span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;">)(((</span><span style="color: blue;"><span style="font-size: small;">int</span></span><span style="font-size: small;">)lParam >> 16) & 0xFFFF);
</span><span style="color: #3d85c6;"><span style="font-size: small;">ModifierKeys </span></span><span style="font-size: small;">modifier = (</span><span style="color: #3d85c6;"><span style="font-size: small;">ModifierKeys</span></span><span style="font-size: small;">)((</span><span style="color: blue;"><span style="font-size: small;">int</span></span><span style="font-size: small;">)lParam & 0xFFFF);
</span><span style="color: green;"><span style="font-size: small;">// invoke the event to notify the parent.</span></span><span style="font-size: small;">
KeyPressed(modifier, key);
}
</span><span style="color: blue;"><span style="font-size: small;">return</span></span><span style="font-size: small;"> IntPtr.Zero;
}</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">
</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana; white-space: normal;"><span style="font-size: small;">Now we just ask an underlying mechanism of WPF to kindly send us all the messages. We can preferably do this when the window has loaded.</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana; white-space: normal;"><span style="font-size: small;"><span style="font-family: Consolas; font-size: 13px; white-space: pre;"><span style="color: #3d85c6;"><span style="font-size: small;">HwndSource </span></span><span style="font-size: small;">src = </span><span style="color: #3d85c6;"><span style="font-size: small;">HwndSource</span></span><span style="font-size: small;">.FromHwnd(</span><span style="color: blue;"><span style="font-size: small;">new</span></span><span style="font-size: small;"> </span><span style="color: #3d85c6;"><span style="font-size: small;">WindowInteropHelper</span></span><span style="font-size: small;">(</span><span style="color: blue;"><span style="font-size: small;">this</span></span><span style="font-size: small;">).Handle); </span></span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small;"><span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;"><span style="font-family: Verdana; font-size: 13px;">
<br />
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-size: small;">src.AddHook(</span><span style="color: blue;"><span style="font-size: small;">new</span></span><span style="font-size: small;"> </span><span style="color: #3d85c6;"><span style="font-size: small;">HwndSourceHook</span></span><span style="font-size: small;">(WndProc));</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small;"><span style="font-family: verdana; font-size: 16px; white-space: normal;"><span style="font-size: small;">
</span>
<br />
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><b><span style="font-size: small;">
</span></b></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><b><span style="font-size: small;">Summary of global hot-key listening</span></b></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><b><span style="font-size: small;">
</span></b></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">We have now done the following:</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><ul>
<li><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">Imported the RegisterHotKey( .. ) method from user32.dll</span></span></span></li>
<li><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">Used it to register a hot-key combo i.e Ctrl+Shift+P</span></span></span></li>
<li><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">Getting our code to parse messages in WndProc</span></span></span></li>
<ul>
<li><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">In Windows.Form: By overriding WndProc( .. )</span></span></span></li>
<li><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">In WPF: By creating WndProc( .. ) and adding a hook<span style="font-family: Consolas; font-size: 13px; white-space: pre;"> </span></span></span></span></li>
</ul>
</ul>
<div>
<span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">These are the main steps, and our application should now be reacting to the global hot-keys that we want.</span></span></span><br />
<span style="font-family: verdana; font-size: medium;"><span class="Apple-style-span" style="font-size: 16px; white-space: normal;">
</span></span><br />
<span class="Apple-style-span" style="font-family: verdana; font-size: 16px; font-weight: bold; white-space: normal;">Sources and tips</span><br />
<span style="font-family: verdana; font-size: medium;"><span class="Apple-style-span" style="font-size: 16px; white-space: normal;"><b>
</b></span></span><br />
<span class="Apple-style-span" style="font-family: verdana; font-size: 13px;"><span style="white-space: normal;"><span style="font-size: small;">Thanks</span></span><span style="white-space: normal;"><span style="font-size: small;"> to </span><span style="font-size: small;">C</span><span style="font-family: Consolas; white-space: pre;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">hristian Liensberger for </span><a href="http://www.liensberger.it/web/blog/?p=207"><span style="font-size: small;">his article on hooks in C#</span></a><span style="font-size: small;">.</span></span></span></span></span></span></div>
<div>
<span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">Thanks to softwerx for his response </span><a href="http://stackoverflow.com/questions/624367/how-to-handle-wndproc-messages-in-wpf"><span style="font-size: small;">showing how to use WndProc in WPF</span></a><span style="font-size: small;">.</span></span></span></div>
<div>
<span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">
</span></span></span></div>
<div>
<span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">The Keys enum in Win</span></span><span style="white-space: normal;"><span style="font-size: small;">dows.Forms can be used when registering and parsing keys. In</span><span style="font-size: small;"> a WPF p</span><span style="font-size: small;">rojec</span><span style="font-size: small;">t one can add a reference to System.Windows.Forms and then add:</span></span></span><br />
<span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span><br />
<span style="font-size: 13px;"><span style="color: blue;"><span style="font-size: small;">using</span></span><span style="font-size: small;"> FormsNS = System.Windows.Forms;</span></span></div>
<div>
<span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;"><span style="font-family: Verdana; font-size: 13px;"></span></span></span><br />
<span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;"><span style="font-family: Verdana; font-size: 13px;"></span></span></span><br />
<span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;"><span style="font-family: Verdana; font-size: 13px;"><pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: verdana;"><span style="white-space: normal;"><span style="font-size: small;">This will avoid conflicts with MessageBox for example in WPF vs. Forms. We can now easily register and keys like this:</span></span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-family: Verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;">
</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="color: green;">// Register a hot key</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small;"><span style="font-family: verdana; font-size: medium;"><span style="font-size: 16px; white-space: normal;"><span style="font-family: Verdana; font-size: 13px;">
<br />
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="color: blue;"><span style="font-size: small;">if</span></span><span style="font-size: small;"> (!RegisterHotKey(handle, 1, (</span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;">)(</span><span style="color: #3d85c6;"><span style="font-size: small;">ModifierKeys</span></span><span style="font-size: small;">.Alt | </span><span style="color: #3d85c6;"><span style="font-size: small;">ModifierKeys</span></span><span style="font-size: small;">.Control), (</span><span style="color: blue;"><span style="font-size: small;">uint</span></span><span style="font-size: small;">)FormsNS.</span><span style="color: #3d85c6;"><span style="font-size: small;">Keys</span></span><span style="font-size: small;">.Down))
</span><span style="color: blue;"><span style="font-size: small;">throw</span></span><span style="font-size: small;"> </span><span style="color: blue;"><span style="font-size: small;">new</span></span><span style="font-size: small;"> InvalidOperationException(</span><span style="color: #006080;"><span style="font-size: small;">"Could not register the hot key"</span></span><span style="font-size: small;">);</span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace;"><span style="font-size: small;"><span style="font-family: verdana; font-size: 16px; white-space: normal;">This way we don't need to define "virtual key-codes", since they correspond to the uint value of keys in Keys.</span></span></pre>
<pre class="csharpcode" style="background-color: white; color: black; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small;"></pre>
</span></span></span></pre>
</span></span></span></div>
</pre>
</span></pre>
</span></span></span></pre>
</span>Anonymoushttp://www.blogger.com/profile/12809344426011810126noreply@blogger.com2