Seay

Seay 查看完整档案

武汉编辑  |  填写毕业院校HX  |  工程师 编辑 seay.me 编辑
编辑

一名.NET开发者,同时也热衷于前端开发以及其他的开发语言,混迹于github、博客园、开源中国、SegmentFault等技术型社区,个人站点:http://seay.me

新浪微博:Seay

个人动态

Seay 关注了用户 · 2017-11-14

竹叶子 @zhuyezi

关注 3

Seay 发布了文章 · 2017-01-20

在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标

前言

FontAwesome 大家都不陌生,精美的图标,出现在各式各样的网页中。
最近在做 Windows Forms 应用程序,要求美观,就想能不能把 FontAwesome 图标用上,于是就有了本文。

本人已经将 FontAwesome 进行了封装,并上传到了 GitHub 和 NuGet。

样图

sample application

简介

下面是解决方案列表:
solution

|- .nuget
|- sample
   |--- FontAwesomeNet.Sample        # Windows Forms Samlpe
   |--- FontAwesomeNet.Wpf.Sample    # WPF Samlpe
|- src
   |--- FontAwesomeNet   # FontAwesome for .NET library

使用

可以参考示例源码。

0. 安装字体

安装过请忽略,地址是:fontawesome-webfont-4.7.0.ttf

1. 安装类库

PM> Install-Package FontAwesomeNet

2. 添加命名空间

using FontAwesomeNet;

3. 生成图片(Image)或图标(Icon)

使用的是 FontAwesome 静态类。

获取字体图标名称:

// get FontAwesome icon class names(type is Dictionary<string, int>)
string[] names = FontAwesome.TypeDict.Select(v => v.Key).ToArray();

获取字体图标名称对应的Unicode码:

// use FontAwesome icon class name get FontAwesome icon Unicode value
int val = FontAwesome.TypeDict["fa-heart"];//0xf004

获取图片和图标:

只有这两个方法。

Bitmap bmp = FontAwesome.GetImage(val);//0xf004
Icon ico = FontAwesome.GetIcon(val);//0xf004

修改默认参数:

直接对静态字段赋值即可。

FontAwesome.IconSize = 128;//change icon size
FontAwesome.ForeColer = Color.Purple;//change icon forecolor
...

如有不好的地方,欢迎大家更正,谢谢。

查看原文

赞 0 收藏 1 评论 4

Seay 发布了文章 · 2017-01-17

jekyll 3.3.1 | Error: invalid byte sequence in GBK

Execute command

bundle exec jekyll serve

Error messages

Liquid Exception: invalid byte sequence in GBK in _layouts/redirect.html
jekyll 3.3.1 | Error:  invalid byte sequence in GBK

This error is on the Windows System.

Resolve methods

Command Line Prompt

chcp 65001
bundle exec jekyll serve

Bash Shell

$ export LC_ALL=en_US.UTF-8
$ export LANG=en_US.UTF-8
$ jekyll --server --auto
$ bundle exec jekyll serve
查看原文

赞 1 收藏 0 评论 0

Seay 发布了文章 · 2017-01-06

C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”

Q:

在反序列化 Xml 字符串为 Xml 对象时,抛出如下异常。
Xml反序列化异常

即在 XML文档(0, 0)中有一个错误:缺少根元素。

A:

首先看下代码:

StringBuilder sb = new StringBuilder();
using (MemoryStream stream = new MemoryStream())
{
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(sb.ToString().Trim());
    writer.Flush();

    //stream.Position=0;
    // or
    //stream.Seek(0, SeekOrigin.Begin);

    StreamReader reader = new StreamReader(stream);
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
    object obj = xmlSerializer.Deserialize(reader);

    reader.Close();
    reader.Close();

    writer.Close();
    writer.Dispose();
}

抛出异常是在object obj = xmlSerializer.Deserialize(reader);这里出现的。

问题在于writer.Write(sb.ToString().Trim());这里,原因是进行了写入操作,最后流的位置停留在尾部。因此,在反序列化之前将流的位置定位到开始 0 的位置即可。

这里就是在 上面注释的地方。

查看原文

赞 0 收藏 0 评论 0

Seay 赞了回答 · 2016-11-29

解决单行注释应该放在行尾还是代码上方呢?

行注释的话一般放在代码后面,块注释的话放在代码上边
具体可以参考 链接描述

关注 28 回答 25

Seay 关注了问题 · 2016-11-18

解决本地仓库(里面已有文件)关联到远程库?

1.本地仓库已有文件

2.如何将关联的远程库中的内容 拉到本地仓库来

我知道的,如果先有远程库,可以用git clone
如果本地仓库是空的没有任何东西 可以用git pull将远程库的东西拉到本地仓库来

现在我有一个有文件的仓库与一个远程库关联,如何将远程库中的内容拉到本地来
我用git pull origin master:master 会得到如下的错误

图片描述

关注 9 回答 7

Seay 回答了问题 · 2016-11-18

解决本地仓库(里面已有文件)关联到远程库?

有冲突了,你可以先 git fetch origin master,然后处理冲突文件,处理完后 add-commit-push 这一套。

关注 9 回答 7

Seay 关注了问题 · 2016-11-18

如何去掉百度地图api中的建筑物名称

clipboard.png
如图,如何去掉圈着的东西

关注 2 回答 1

Seay 回答了问题 · 2016-11-18

如何去掉百度地图api中的建筑物名称

利用节点的css来实现,将其 display 设置为 none

关注 2 回答 1

Seay 关注了问题 · 2016-11-18

autofac实现热注册思路

项目上线后一些接口可能功能不稳定,或者需要动态的增加一些内容,
如果使用Autofac,能不能实现不重启应用只更改配置文件,组件自动注册到Container中,有好的思路吗?

关注 3 回答 2

Seay 回答了问题 · 2016-11-18

autofac实现热注册思路

监控配置文件,当文件发生改变时,判断是否是需要重新注册的组件,然后再执行注册。

关注 3 回答 2

Seay 回答了问题 · 2016-11-18

解决php 数组的合并的算法问题?

循环数组,然后重组成一个新的数组。

关注 6 回答 4

Seay 关注了问题 · 2016-11-18

解决php 数组的合并的算法问题?

现在有两个二维数组,第一个数组中子元素下包含着,第二个二维数组的索引,现在想将数组合并成第一个数组直接对应第二个数组下的子元素
例:

array1 => array(
'key1' => array(
        0 => 'a',
        1 => 'b',
    ),
 'key2'=> array(
        0 => 'd',
        1 => 'e',
        2 => 'f'
 )   
 。。。。
)

array2 => array(
    'a' =>array(
        0 => 1,
        1 => 2 ,
        2 => 3,
    ),
    'b' => array(
        0 => 4,
        1 => 5 ,
        2 => 6,
    ),
    
   。。。。
 
    'f' => array(
         0 => 7,
        1 => 8 ,
        2 => 9,
    )
)

希望能够得到的输出结果是

array(
'key1' => array(
        0 => 1,
        1 => 2 ,
        2 => 3,
        3 => 4,
        4 => 5 ,
        5 => 6,
)
'key2' => array(
        ....
)
....
)

   即 数组1的键 => array( 包含数组二的索引)
   数组2的键  => array( 是数组1 每个元素的子元素)

求:

  数组1的键 => array(对应的数组2下所有的元素)

关注 6 回答 4

Seay 赞了文章 · 2016-10-18

探究Gulp的Stream

来自Gulp的难题

描述Gulp的项目构建过程的代码,并不总是简单易懂的。

比如Gulp的这份recipe

var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var gutil = require('gulp-util');

gulp.task('javascript', function () {
  var b = browserify({
    entries: './entry.js',
    debug: true
  });

  return b.bundle()
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(uglify())
    .on('error', gutil.log)
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest('./dist/js/'));
});

这是一个使用Browserify及Uglify并生成Source Map的例子。请想一下这样几个问题:

  • b.bundle()生成了什么,为什么也可以.pipe()

  • 为什么不是从gulp.src()开始?

  • 为什么还要vinyl-source-streamvinyl-buffer?它们是什么?

  • 添加在中间的.on('error', gutil.log)有什么作用?

要回答这些问题,就需要对Gulp做更深入的了解,这可以分成几个要素。

要素之一:Stream

你可能也在最初开始使用Gulp的时候就听说过:Gulp是一个有关Stream数据流)的构建系统。这句话的意思是,Gulp本身使用了Node的Stream

Stream如其名字所示的“流”那样,就像是工厂的流水线。你要加工一个产品,不用全部在一个位置完成,而是可以拆分成多道工序。产品从第一道工序开始,第一道工序完成后,输出然后流入第二道工序,然后再第三道工序...一方面,大批量的产品需求也不用等到全部完工(这通常很久),而是可以完工一个就拿到一个。另一方面,复杂的加工过程被分割成一系列独立的工序,这些工序可以反复使用,还可以在需要的时候进行替换和重组。这就是Stream的理念。

Stream在Node中的应用十分广泛,几乎所有Node程序都在某种程度上用到了Stream。

管道

Stream有一个很基本的操作叫做管道pipe)。Stream是水流,而管道可以从一个流的输出口,接到另一个流的输入口,从而控制流向。如果用前面的流水线工序来说的话,就是连接工序的传输带了。

pipes

Node的Stream有一个方法pipe(),也就是管道操作对应的方法。它一般这样用:

src.pipe(dst)

其中srcdst都是stream,分别代表源和目标。也就是说,流src的输出,将作为输入转到流dst。此外,这个方法返回目标流(比如这里.pipe(dst)返回dst),因此可以链式调用:

a.pipe(b).pipe(c).pipe(d)

内存操作

Stream的整个操作过程,都在内存中进行。因此,相比Grunt,使用Stream的Gulp进行多步操作并不需要创建中间文件,可以省去额外的srcdest

事件

Node的Stream都是Node事件对象EventEmitter的实例,它们可以通过.on()添加事件侦听。

你可以查看EventEmitter的API文档

类型

在现在的Node里,Stream被分为4类,分别是Readable只读)、Writable只写)、Duplex双向)、 Transform转换)。其中Duplex就是指可读可写,而Transform也是Duplex,只不过输出是由输入计算得到的,因此算作Duplex的特例。

Readable Stream和Writable Stream分别有不同的API及事件(例如readable.read()writable.write()),Duplex Stream和Transform Stream因为是可读可写,因此拥有前两者的全部特性。

例子

虽然Node中可以通过require("stream")引用Stream,但比较少会需要这样直接使用。大部分情况下,我们用的是Stream Consumers,也就是具有Stream特性的各种子类。

Node中许多核心包都用到了Stream,它们也是Stream Consumers。以下是一个使用Stream完成文件复制的例子:

var fs = require("fs");
var r = fs.createReadStream("nyanpass.txt");
var w = fs.createWriteStream("nyanpass.copy.txt");
r.pipe(w).on("finish", function(){
    console.log("Write complete.");
});

其中,fs.createReadStream()创建了Readable Stream的rfs.createWriteStream()创建了Writable Stream的w,然后r.pipe(w)这个管道方法就可以完成数据从rw的流动。

如前文所说,Stream是EventEmitter的实例,因此这里的on()方法为w添加了事件侦听,事件finish是Writable Stream的一个事件,触发于写入操作完成。

更多有关Stream的介绍,推荐阅读Stream HandbookStream API

要素之二:Vinyl文件系统

虽然Gulp使用的是Stream,但却不是普通的Node Stream,实际上,Gulp(以及Gulp插件)用的应该叫做Vinyl File Object Stream

这里的Vinyl,是一种虚拟文件格式。Vinyl主要用两个属性来描述文件,它们分别是路径path)及内容contents)。具体来说,Vinyl并不神秘,它仍然是JavaScript Object。Vinyl官方给了这样的示例:

var File = require('vinyl');

var coffeeFile = new File({
  cwd: "/",
  base: "/test/",
  path: "/test/file.coffee",
  contents: new Buffer("test = 123")
});

从这段代码可以看出,Vinyl是Object,pathcontents也正是这个Object的属性。

Vinyl的意义

Gulp为什么不使用普通的Node Stream呢?请看这段代码:

gulp.task("css", function(){
    gulp.src("./stylesheets/src/**/*.css")
        .pipe(gulp.dest("./stylesheets/dest"));
});

虽然这段代码没有用到任何Gulp插件,但包含了我们最为熟悉的gulp.src()gulp.dest()。这段代码是有效果的,就是将一个目录下的全部.css文件,都复制到了另一个目录。这其中还有一个很重要的特性,那就是所有原目录下的文件树,包含子目录、文件名等,都原封不动地保留了下来。

普通的Node Stream只传输String或Buffer类型,也就是只关注“内容”。但Gulp不只用到了文件的内容,而且还用到了这个文件的相关信息(比如路径)。因此,Gulp的Stream是Object风格的,也就是Vinyl File Object了。到这里,你也知道了为什么有contentspath这样的多个属性了。

vinyl-fs

Gulp并没有直接使用vinyl,而是用了一个叫做vinyl-fs的模块(和vinyl一样,都是npm)。vinyl-fs相当于vinyl的文件系统适配器,它提供三个方法:.src().dest().watch(),其中.src()将生成Vinyl File Object,而.dest()将使用Vinyl File Object,进行写入操作。

在Gulp源码index.js中,可以看到这样的对应关系:

var vfs = require('vinyl-fs');
// ...
Gulp.prototype.src = vfs.src;
Gulp.prototype.dest = vfs.dest;
// ...

也就是说,gulp.src()gulp.dest()直接来源于vinyl-fs。

类型

Vinyl File Object的contents可以有三种类型StreamBuffer(二进制数据)、Null(就是JavaScript里的null)。需要注意的是,各类Gulp插件虽然操作的都是Vinyl File Object,但可能会要求不同的类型

在使用Gulp过程中,可能会碰到incompatible streams的问题,像这样:

incompatible streams

这个问题的原因一般都是Stream与Buffer的类型差异。Stream如前文介绍,特性是可以把数据分成小块,一段一段地传输,而Buffer则是整个文件作为一个整体传输。可以想到,不同的Gulp插件做的事情不同,因此可能不支持某一种类型。例如,gulp-uglify这种需要对JavaScript代码做语法分析的,就必须保证代码的完整性,因此,gulp-uglify只支持Buffer类型的Vinyl File Object。

gulp.src()方法默认会返回Buffer类型,如果想要Stream类型,可以这样指明:

gulp.src("*.js", {buffer: false})

在Gulp的插件编写指南中,也可以找到Using buffersDealing with streams这样两种类型的参考。

Stream转换

为了让Gulp可以更多地利用当前Node生态体系的Stream,出现了许多Stream转换模块。下面介绍一些比较常用的。

vinyl-source-stream

vinyl-source-stream可以把普通的Node Stream转换为Vinyl File Object Stream。这样,相当于就可以把普通Node Stream连接到Gulp体系内。具体用法是:

var fs = require("fs");
var source = require('vinyl-source-stream');
var gulp = require('gulp');

var nodeStream = fs.createReadStream("komari.txt");
nodeStream
    .pipe(source("hotaru.txt"))
    .pipe(gulp.dest("./"));

这段代码中的Stream管道,作为起始的并不是gulp.src(),而是普通的Node Stream。但经过vinyl-source-stream的转换后,就可以用gulp.dest()进行输出。其中source([filename])就是调用转换,我们知道Vinyl至少要有contents和path,而这里的原Node Stream只提供了contents,因此还要指定一个filename作为path。

vinyl-source-stream中的stream,指的是生成的Vinyl File Object,其contents类型是Stream。类似的,还有vinyl-source-buffer,它的作用相同,只是生成的contents类型是Buffer。

vinyl-buffer

vinyl-buffer接收Vinyl File Object作为输入,然后判断其contents类型,如果是Stream就转换为Buffer。

很多常用的Gulp插件如gulp-sourcemaps、gulp-uglify,都只支持Buffer类型,因此vinyl-buffer可以在需要的时候派上用场。

Gulp错误处理

Gulp有一个比较令人头疼的问题是,如果管道中有任意一个插件运行失败,整个Gulp进程就会挂掉。尤其在使用gulp.watch()做即时更新的时候,仅仅是临时更改了代码产生了语法错误,就可能使得watch挂掉,又需要到控制台里开启一遍。

对错误进行处理就可以改善这个问题。前面提到过,Stream可以通过.on()添加事件侦听。对应的,在可能产生错误的插件的位置后面,加入on("error"),就可以做错误处理:

gulp.task("css", function() {
    return gulp.src(["./stylesheets/src/**/*.scss"])
        .pipe(sass())
        .on("error", function(error) {
            console.log(error.toString());
            this.emit("end");
        })
        .pipe(gulp.dest("./stylesheets/dest"));
});

如果你不想这样自己定义错误处理函数,可以考虑gulp-util.log()方法。

另外,这种方法可能会需要在多个位置加入on("error"),此时推荐gulp-plumber,这个插件可以很方便地处理整个管道内的错误。

据说Gulp下一版本,Gulp 4,将大幅改进Gulp的错误处理功能,敬请期待。

解答

现在,来回答本文开头的问题吧。

b.bundle()生成了什么,为什么也可以.pipe()b.bundle()生成了Node Stream中的Readable Stream,而Readable Stream有管道方法pipe()

为什么不是从gulp.src()开始?Browserify来自Node体系而不是Gulp体系,要结合Gulp和Browserify,适当的做法是先从Browserify生成的普通Node Stream开始,然后再转换为VInyl File Object Stream连接到Gulp体系中。

为什么还要vinyl-source-streamvinyl-buffer?它们是什么?因为Gulp插件的输入必须是Buffer或Stream类型的Vinyl File Object。它们分别是具有不同功能的Stream转换模块。

添加在中间的.on('error', gutil.log)有什么作用?错误处理,以便调试问题。

结语

再次确认,Gulp是一个有关Stream的构建系统。Gulp对其插件有非常严格的要求(看看插件指南就可以知道),认为插件必须专注于单一事务。这也许算是Gulp对Stream理念的推崇。

尝试用Gulp完成更高级、更个性化的构建工作吧!

(重新编辑自我的博客,原文地址:http://acgtofe.com/posts/2015/09/dive-into-gulp-stream

查看原文

赞 34 收藏 89 评论 11

Seay 关注了问题 · 2016-09-23

git远程仓库问题(提交。回退)

1.从master分支克隆了一个项目到本地,
现在又fork了一个仓库,
如何把本地修改的代码提交到fork的远程仓库
而不是第一次克隆的仓库呢

2.远程fork仓库如何版本回退

关注 4 回答 2

Seay 回答了问题 · 2016-09-23

git远程仓库问题(提交。回退)

  1. 关于 git 同步到 fork 仓库可以参考下:Git同步原始仓库到Fork仓库中

  2. 版本退回可以使用如下命令:

git reset --hard HEAD~3#3指的是退回到最近的第几次提交,是倒数的

或者是:

git reset --hard 对于版本的哈希值

详见:廖雪峰Git教程:版本回退

关注 4 回答 2

Seay 回答了问题 · 2016-09-23

一个简单的批处理文件

批处理可以这么写:

@echo off
G:#前面是盘符
cd 绝对路径
npm run dev

关注 2 回答 2

Seay 关注了问题 · 2016-09-23

一个简单的批处理文件

目前的需求是这样的, 在本机跑了一个项目, 需要一开机就运行, 具体流程是这样(系统是windows)

cd 到某个目录
键入npm run dev
回车运行

个人感觉应该可以用批处理文件来解决, 但具体该怎么写呢?
求解!

关注 2 回答 2

Seay 发布了文章 · 2016-08-25

C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper

前言

在开发应用程序时,通常只让程序运行一个实例。所以,就要判断程序是否已经运行。

下面是我自己在项目中使用到,封装好的帮助类。有 普通的 C# 应用程序 和 Windows CE 和 Windows Mobile 应用程序使用的方法。

主要是通过 System.Threading.Mutex 类 和 Win32 API 来实现,下面就是各自的代码,调用示例在最后面。

普通 C# 应用程序

主要是 Windows 窗体应用程序和控制台程序。

1. 使用 System.Threading.Mutex 类

参考:Mutex 类(System.Threading)

using System.Threading;

namespace XY.Util.Helper
{
    /// <summary>
    /// Mutex helper
    /// </summary>
    public class MutexHelper
    {
        /// <summary>
        /// 判断程序是否已经运行
        /// <param name="assembly">程序集实例</param>
        /// </summary>
        /// <returns>
        /// true: 程序已运行
        /// false: 程序未运行
        /// </returns>
        public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
        {
            string strAppName = assembly.GetName().Name;
            return IsApplicationOnRun(strAppName);
        }

        /// <summary>
        /// 判断程序是否已经运行
        /// <param name="assemblyName">程序名称</param>
        /// </summary>
        /// <returns>
        /// true: 程序已运行
        /// false: 程序未运行
        /// </returns>
        public static bool IsApplicationOnRun(string assemblyName)
        {
            bool ret = false;
            //第一个参数:true--给调用线程赋予互斥体的初始所属权  
            //第一个参数:互斥体的名称  
            //第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回true
            Mutex mutex = new Mutex(true, assemblyName, out ret);
            return !ret;
        }
    }
}

2. 使用 Win32 API

using System;
using System.Runtime.InteropServices;

namespace XY.Util.Helper
{
    /// <summary>
    /// Mutex helper
    /// </summary>
    public class MutexHelper
    {
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenMutex(uint dwDesiredAccess, bool bInitialOwner, string lpName);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);

        /// <summary>
        /// 判断程序是否已经运行
        /// <param name="assembly">程序集实例</param>
        /// </summary>
        /// <returns>
        /// true: 程序已运行
        /// false: 程序未运行
        /// </returns>
        public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
        {
            string strAppName = assembly.GetName().Name;
            return IsApplicationOnRun(strAppName);
        }

        /// <summary>
        /// 判断程序是否已经运行
        /// <param name="assemblyName">程序名称</param>
        /// </summary>
        /// <returns>
        /// true: 程序已运行
        /// false: 程序未运行
        /// </returns>
        public static bool IsApplicationOnRun(string assemblyName)
        {
            bool ret = false;

            if (OpenMutex(0x1F0001, false, assemblyName) == IntPtr.Zero)
            {
                CreateMutex(IntPtr.Zero, false, assemblyName);
                ret = true;
            }

            return ret;
        }
    }
}

Windows CE | Windows Mobile 应用程序

在 Windows CE 和 Windows Mobile 中实现,是通过 Win32 API实现的,下面是封装的帮助类:

参考:

using System;
using System.Runtime.InteropServices;

namespace XY.Util.Helper
{
    /// <summary>
    /// Mutex helper
    /// </summary>
    public class MutexHelper
    {
        [DllImport("coredll.dll", EntryPoint = "CreateMutex", SetLastError = true)]
        public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);

        [DllImport("coredll.dll", EntryPoint = "ReleaseMutex", SetLastError = true)]
        public static extern bool ReleaseMutex(IntPtr hMutex);

        private const int ERROR_ALREADY_EXISTS = 0183;

        /// <summary>
        /// 判断程序是否已经运行
        /// <param name="assembly">程序集实例</param>
        /// </summary>
        /// <returns>
        /// true: 程序已运行
        /// false: 程序未运行
        /// </returns>
        public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
        {
            string strAppName = assembly.GetName().Name;
            return IsApplicationOnRun(strAppName);
        }

        /// <summary>
        /// 判断程序是否已经运行
        /// <param name="assemblyName">程序名称</param>
        /// </summary>
        /// <returns>
        /// true: 程序已运行
        /// false: 程序未运行
        /// </returns>
        public static bool IsApplicationOnRun(string assemblyName)
        {
            IntPtr hMutex = CreateMutex(IntPtr.Zero, true, assemblyName);
            if (hMutex == IntPtr.Zero)
            {
                throw new ApplicationException("Failure creating mutex: " + Marshal.GetLastWin32Error().ToString("X"));
            }
            if (Marshal.GetLastWin32Error() == ERROR_ALREADY_EXISTS)
            {
                ReleaseMutex(hMutex);
                return true;
            }
            return false;
        }
    }
}

示例代码

调用示例:

using System;
using System.Reflection;
using XY.Util.Helper;

namespace MutexTest
{
    static class Program
    {
        [MTAThread]
        static void Main(string[] args)
        {
            bool run;

            //方式一
            run = MutexHelper.IsApplicationOnRun("ApplicationName");

            //方式二
            run = MutexHelper.IsApplicationOnRun(Assembly.GetExecutingAssembly());

            if (run)
            {
                // application is running...
                // Exit.
            }
            else
            {
                // start application ...
                // startup...
            }
        }
    }
}
查看原文

赞 1 收藏 0 评论 0

Seay 发布了文章 · 2016-08-04

『.NET Core CLI工具文档』(十四)dotnet-install 脚本参考

说明:本文是个人翻译文章,由于个人水平有限,有不对的地方请大家帮忙更正。
原文:dotnet-install scripts reference
翻译:dotnet-install 脚本参考

名称

dotnet-install.ps1 | dotnet-install.sh - 用于安装命令行界面(CLI)工具的脚本和共享运行时

概要

Windows:

dotnet-install.ps1 [-Channel] [-Version] [-InstallDir] [-Debug] [-NoPath] [-SharedRuntime]

OS X/Linux:

dotnet-install.sh [--channel] [--version] [--install-dir] [--debug] [--no-path] [--shared-runtime]

描述

dotnet-install 安装脚本用来执行非管理员安装 CLI 工具链和共享运行时。你可以从我们的 CLI GitHub repo 下载脚本。

其主要用于帮助自动化场景和非管理员安装。有两个脚本,一个是在 Windows 上工作的 PowerShell 和另一个在 Linux/OS X 上工作的 bash 脚本。他们两者有同样的行为。Bash 脚本也可以“理解”为 PowerShell 的切换,因此你可以全线使用他们。

安装脚本会从 CLI 下载 ZIP/tarball(压缩包)文件生成,并且将可能在默认位置或者在通过 --install-dir 指定的位置进行安装。默认情况下,该安装脚本将下载 SDK 和安装它;如果你仅仅想获取共享运行时,你可以指定 --shared-runtime 参数。

默认情况下,安装脚本将安装位置添加到当前会话的 $PATH 中。这可以被覆盖,如果使用 --no-path 参数。

在运行脚本之前,请安装所有的必须 依赖

你可以使用 --version 参数安装一个指定的版本。该指定的版本需要由 3 部分的版本(例如:1.0.0-13232)。如果忽略,它将默认到被调用脚本的上级文件夹中找到的第一个包含 sdkVersion节点的 global.json 文件。如果不存在,它会使用最新的。

你也可以使用这个脚本通过用 --debug 参数来获得 SDK 或共享运行时的调试符号的调试二进制文件。如果第一次安装你不这样做,稍后实际上你确实需要调试符号,你可以使用这个参数和你安装的版本重新运行脚本。

选项

不同脚本实现的选项。

PowerShell (Windows)

-Channel [CHANNEL]

安装的渠道(例如:“future”、“preview”、“production”)。默认版本是“Production”。

-Version [VERSION]

安装的 CLI 版本。你需要指定由 3 部分组成的版本(例如:1.0.0-13232)。如果忽略,它将默认到被调用脚本的上级文件夹中找到的第一个包含 sdkVersion节点的 global.json 文件。如果不存在,它会使用最新的。

-InstallDir [DIR]

安装的路径。如果目录不存在则创建它。默认值是 %LocalAppData%\.dotnet

-Debug

true 表明应该使用包含调试符号的更大包;否则,false。默认值是 false

-NoPath

true 表明前缀/安装目录不导出到当前会话的路径;否则,false。默认值是 false,那就是,PATH 被修改。这使得 CLI 工具安装后立即可用。

-SharedRuntime

true 仅仅安装共享运行时。false 安装整个 SDK。默认值是 false

Bash (OS X/Linux)

--channel [CHANNEL]

安装的渠道(例如:“future”、“preview”、“production”)。默认版本是“Production”。

--version [VERSION]

安装的 CLI 版本。你需要指定由 3 部分组成的版本(例如:1.0.0-13232)。如果忽略,它将默认到第一个包含 sdkVersion节点的 global.json 文件。如果不存在,它会使用最新的。

--install-dir [DIR]

安装的路径。如果目录不存在则创建它。默认值是 %HOME%/.dotnet

--debug

true 表明应该使用包含调试符号的更大包;否则,false。默认值是 false

--no-path

true 表明前缀/安装目录不导出到当前会话的路径;否则,false。默认值是 false,那就是,PATH 被修改。这使得 CLI 工具安装后立即可用。

--shared-runtime

true 仅仅安装共享运行时。false 安装整个 SDK。默认值是 false

例子

Windows:

./dotnet-install.ps1 -Channel Future

OS X/Linux:

./dotnet-install.sh --channel Future

安装最新的开发版本到默认位置。

Windows:

./dotnet-install.ps1 -Channel preview -InstallDir C:\cli

OS X/Linux:

./dotnet-install.sh --channel preview --install-dir ~/cli

安装最新的预览版本到指定的位置。

查看原文

赞 0 收藏 1 评论 0