WPF快速入门——布局介绍

为什么要布局

布局和房子的格局具有着相似的概念,都是为了提供更好的用户体验而进行 设计。下面我们讲讲几个常用的布局面板

布局面板

WPF中有许多布局面板,下面将会介绍几个常用的布局面板,其中最常用的应该是Grid,StackPanel和DockPanel三大布局面板。

Grid和UniformGrid

Grid面板在WPF界面开发中,应该是使用最多的布局面板了。其功能为网格布局,下面以一个例子来解释一下其功能:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="2*"/>
        <ColumnDefinition Width="3*"/>
    </Grid.ColumnDefinitions>
</Grid>

在本示例中,Grid布局为3行3列,其中行高采用了等分,列宽比例为1:2:3。其中行高和列宽都用到了*表示,这里也可以写具体的数值,或者填写auto*auto都是一种自适应的布局,不同之处在于:*可以说是对于外部的自适应 —— 自动填满;而auto可以说是对于内部的自适应 —— 最小空间占用。

在布局中处理好行列后,就可以向里面添加控件了,在使用控件时,需要为控件设置在哪一行哪一列(如,第一行第一列[从0开始]:Grid.Row="1" Grid.Column="1")。

与Grid非常相似的一个面板就是UniformGrid了。虽然UniformGrid不是在Grid上继承下来的,但是在使用上可以说UniformGrid是Grid的一个特殊化处理。下面列举几点它们的区别:

  • Grid需要通过RowDefinitions和ColumnDefinition来定义行和列的个数,UniformGrid只需要通过属性Rows和Columns设置
  • Grid行高列宽手动设置,UniformGrid中完全等分。
  • Grid中的控件必须手动指定行列,否则只能在第0行第0列;UniformGrid中自动排列。
  • Grid中某行某列可以放多个控件;而在UniformGrid中必须嵌套布局面板才可以。

Grid和UniformGrid还有其他的不同,此处不再赘述。而且相对来说,UniformGrid的使用范围较小,最有用的使用情况就是业务表单录入类的界面 —— 需要大量的网格。

WrapPanel和StackPanel

此处之所以将WrapPanel和StackPanel放在一起,是因为他们有一定的相似之处。他们关系和上面的Grid和UniformGrid差不多,没有继承关系,但是StackPanel又有些像WrapPanel的特殊化处理。WrapPanel——流式布局,就像我们的写字一样,一行一行的,或者一列一列的;而StackPanel——堆栈式布局,就像一个不会换行/列的WrapPanel。下面分别说一下它们的使用场景:

WrapPanel除了上面说的写字以外,最常见的应该就是日历了,然后就是各大电商/视频网站中常会见到。而对于StackPanel,最熟悉的场景就是买票排队了,然后在应用中最常见的就是新闻列表、消息列表等(列表类内容)。如果你做的应用需要块状显示结果(多行多列),就用WrapPanel,如果需要条状展示结果(单行多列或多行单列),就用StackPanel。

在上述两个面板中,相对来说,StackPanel会使用的更加频繁一些。

DockPanel

DockPanel是三大最常用面板的最后一个,与前两个相比,使用量上会相对少些。但在我们的生活当中却是最常见的,比如你家里摆放物品时,常会需要哪个哪个靠墙边放。所以这个布局会出现在最不起眼的地方,但有时却是必不可少的。它的作用是让控件靠边(上下左右)停靠,软件应用中的菜单栏是一个比较典型的应用场景。

对于DockPanel还有一点需要注意的是:先到先得,就是先添加的控件先占用部分位置,然后后面添加的控件在剩余部分分割空间,不影响先前的控件 —— 这里控件的前后是指xaml文件中控件定义的位置先后。

Canvas及元素InkCanvas

Canvas是一个以坐标来确认控件位置的布局面板。在Canvas中的控件,需要以Canvas面板左上角为原点来设置坐标。相比之下,Canvas使用的会很少。只有在比较特殊的领域中,Canvas才有其展现的机会。而提到Canvas,还有一个比较特殊的元素InkCanvas,它与Canvas比较相似,但 它并不是布局面板,它直接继承自FrameworkElement;另外,InkCanvas主要用于手写 输入领域。

综合上述内容,Canvas的效率最高,当然它的功能也最弱;如果你去看它们的实现源码,会发现DockPanel和Canvas实现是比较简单的,所以效率也高,而Grid是最复杂的,所以它的效率相对是最低的。故在应用中选择最合适布局面板,有利于提高软件应用的性能;如果自己有能力,也可以自己实现Panel。
面板性能参考:Canvas略高于DockPanel,高于WrapPanel,高于StackPanel,高于Grid —— 由源代码复杂程度大概估算,未进行详细实测。

常与布局组合使用的控件

在使用布局面板时,常常会需要一些辅助的控件来实现一些特殊的功能,下面会介绍几个常见的辅助控件。

Border

Border是一个非常特殊的“控件”。它像是一个面板,但由不是;说它是个控件,它又不继承自Control,而是继承自Decorator。它常用于为面板添加边框。因为面板是不具有边框相关的属性的,如果需要在 布局中添加边框,就需要在相应的布局面板外侧添加Border,以此添加边框。而且Border不仅仅是可以添加边框,还可以处理一些圆角等处理,可以让软件应用更加圆滑。Border与布局面板还有一个主要的区别就是:

  • Border内只能包含一个元素(面板、控件等),所以,想要添加多个控件,就必须先添加一个面板,然后向面板中添加控件。

ScrollViewer

ScrollViewer也是一个常与布局组合使用的控件,与Border不同的是,它确实是一个控件(继承自Control)。用到ScrollView的原因是,布局面板本身是不提供滚动支持的,当内容超出布局面板外侧的大小限制时,我们就无法查看超出内容,此时就需要ScrollViewer来处理了。还有一点与Border相同的是,它里面也只能有一个元素,到添加多个,则必须嵌套布局面板。

GridSplitter

看到GridSplitter名字就应该 知道它是 和Grid组合 使用的,它是用于在运行期间调整界面布局大小的。最常见的就是在左侧列表,右侧具体内容的界面布局中,需要看左侧列表的内容,但列表宽度又太小,此时,添加GridSplitter就可以让用户自己拖动来扩大列表的宽度,以便于查看更多内容。

附加属性

附加属性简单点说就是,这个属性不是元素(如控件)自己的,是别人给它的。最常见的使用场景就是上面的布局面板了,如Grid中,内部控件会有Grid.Column的 属性,这就是一个附加属性;还有如DockPanel中,内部控件会有DockPanel.Dock属性,这也是一个附加属性。当然,附加属性并不是外侧面板给它的,只是上面提到的两个属性,只有在相应的面板中才有效而已。

或者,在往深了说,附加属性不是真正的属性,它是一个方法调用,只是xaml中封装了方法调用,让它看起来是个属性的样子。而在个人所遇到的情况中,自定义附加属性的情况真的是很少很少 ———— 最典型的一次是使用PasswordBox,由于PasswordBox的Password不支持绑定,所以使用到了附加属性来处理,其中内容涉及到了依赖属性,此处不做详细介绍,仅做举例。

上述内容继承结构

WPF快速入门——Hello,World和XAML介绍

个人开发环境 —— 按个人喜好选择:

  • IDE:Visual Studio Community 2015 —— 愿意尝鲜的可以试下VS2017
  • System:Windows 8.1

Hello World

尽管hello,world的例子已经用烂了,但你不可否认它所带来的无限魅力。如果你去查找hello,world起源,会发现许多有趣的事。所以本文仍以hello,world为例开始我们的WPF学习之旅。

创建第一个WPF项目

操作步骤:打开Visual Studio —— 依次点击文件-新建-项目 —— 在弹出的新建项目对话框中的索引目录区域选择已安装-模板-Visual C#-Windows —— 选中对话框列表项中的WPF 应用程序 —— 在对话框下方的名称中输入名称Hello_World —— 点击确定完成项目创建。

创建Hello,World项目

项目结构说明

  • 解决方案Hello_World —— VS解决方案,可以用于同时管理多个项目
    • Hello_World —— 项目,即刚刚新建的Hello,World项目
      • Properties —— 项目属性相关内容设置,包括程序集信息、一些资源等内容
      • 引用 —— 项目中需要的依赖程序集
      • App.config —— 项目配置,在Hello,World项目中可有可无。
      • App.xaml —— 含两个文件App.xaml和App.xaml.cs;此部分功能主要是设置应用的启动窗体及一些样式资源的引用,常用于主窗体显示前的一些准备工作设置。
      • MainWindow.xaml —— 含有两个文件MainWindow.xaml和MainWindow.xaml.cs;.xaml文件为界面设计文件,.cs文件为后台代码文件

Tips:全局异常处理

为了避免应用出现异常后直接退出,我们常会需要添加一个全局的异常捕获处理。处理方法为,在App.xaml.cs中重载OnStartup方法,为DispatcherUnhandleException事件添加处理内容。代码如下:

protected override void OnStartup(StartupEventArgs e)
{
    this.DispatcherUnhandledException += App_DispatcherUnhandledException;
    
    base.OnStartup(e);
}

private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
    //throw new NotImplementedException();
    e.Handled = true;
}

注意:在事件处理中添加你自己的实现内容,可以添加对话框提示等。如果有些异常处理完后,不需要应用退出,则将e.Handled设置为true;如果此处为致命错误,必须退出应用软件,则e.Handled保留原来的false。

XAML基础介绍

XAML文件是以.xaml为后缀的XML文件。其是为了简化UI的创建过程而推出的。它不仅仅在WPF中应用,在微软后续的UMP开发中也是利用此技术进行UI处理。

注:XAML读音为“zammel”

命名空间说明

在XAML文件中,命名空间利用xmlns(xml namespace)来引入。命名空间引入基本格式为:

xmlns:别名="命名空间"

其中默认命名空间可以省略“冒号”和“别名”,另,此处引用的命名空间与cs代码中的还有所不同,cs代码中只能一个空间一个空间引入,而此处的空间可以是多个命名空间的集合 —— URL表示,当然也可以一个一个空间引入。

类对应关系

在我们的示例中MainWindow.xaml根节点Window上有一个属性设置“x:Class”,此属性设置了其所对应的C#代码类。而在我们的MainWindow.xaml.cs的定义中,可以看到MainWindow类含有partial(分部类)修饰符。其实在最终的生成结果中,他们是同一个类,我们可以在obj\Debug目录下看到 MainWindow.g.i.cs文件,它是在生成过程中的一个中间状态,从其内容结构上可以看出它也是MainWindow的一个分部类。如果将XAML文件中的类名修改,程序生成过程就会出现错误,因为MainWindow构造函数 中 的InitializeComponent()方法是xaml文件生成出来的。

注:分部类 —— 就是让你可以将一个类的内容定义到多个文件。—— 据我所知,这应该是.NET中特有的设计 。

基本属性及事件

属性设置其实和在cs代码中设置一样,仅仅是因为换了种写法,封装了一些处理而已。

简单的属性设置

简单属性设置,即可以用一个字符串表示的属性设置,如Name属性。还有就是一些位置Alignment的设置,如HorizontalAlignment可以设置为Center,在XAML文件中,Center是一个字符串,而在类中HorizontalAlignment是一个System.Windows.HorizontalAlignment的枚举类型的属性,所以此处就封装了字符串到Alignment枚举类型的一个转换。不过在我们界面设置的时候,是不太需要关注这一块的。

注:许多控件的Text或Content属性会与标签值(如<a>此处为标签值</a>)冲突 —— 即它们表示同一个属性,所以为了避免冲突,建议,可以直接设置Text或Content的值时,尽量设置在属性上设置,避免在标签中设置属性值。

// 建议
<TextBox Text="hello"></TextBox>
<Button Content="hello"></Button>

// 不建议
<TextBox >hello</TextBox>
<Button >hello</Button>

虽然效果一样,但看得不爽 —— 强迫症。如下方式也是可以的,主要用于复杂的属性设置:

<TextBox >
    <TextBox.Text>hello</TextBox.Text>
</TextBox>
<Button >
    <Button.Content>hello</Button.Content>
</Button>

复杂属性设置

复杂属性的设置表现在无法用一个字符串表示的情况,如颜色背景设置,但我们是单色的情况时,可以直接用一个字符串表示,但是当需要设置渐变色时,就无法一个值表示,所以需要多行语句来表示。

以下为背景色的渐变色设置,其位置变化为默认值,从左上角到右下角渐变:

<Button >
    <Button.Content>hello</Button.Content>
    <Button.Background>
        <LinearGradientBrush>
            <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0" Color="Red"></GradientStop>
                <GradientStop Offset="1" Color="Blue"></GradientStop>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Button.Background>
</Button>

还有一些属性相关内容,将在后面介绍,如附加属性,资源设置等。

添加事件

事件的添加有两种方式,一种是直接在XAML文件中和写属性一样添加 —— 利用自动创建,在后台代码中创建事件的实现。还有一种是在后台代码手动实现。写法纯粹看个人喜好了。

当然,后台代码手动实现的自由度更高一些,如某些事件的注册可能需要在界面加载完后注册会更好一些。个人是推荐在后台代码自己手动加,虽然写的时候会麻烦些,但可以自己整理的比较清晰一些。

Tips:学WPF的好处

  • 就本节内容而言,WPF界面设计采用xml格式,以后以此基础学习网页设计和Android开发会相对简单一些。

MEF基础指南——MEF导入导出

文章缘起

要说写MEF中的导入导出,我想没有哪一篇文章可以比得上微软的官方文档了(至少是我看到的里面没有)。
个人强烈建议看MEF导入导出的人去看微软官方文档,文档地址:

个人喜欢用 Microsoft Help查看器(Help Viewer) 离线查看,如果你也喜欢这样,你可以直接在里面搜索MEF,找到特性化编程模型概述即可。

既然微软官方文档已经很完善了,那本文自然不会在写一遍,故本文更倾向与一篇快速索引参考文。

快速参考

导入导出基础

  1. 无参数导入导出,默认使用当前类或接口,示例如下:

示例中最后a有效,而ia无效;

    public interface IA { }

    /// <summary>
    /// 等价于 [Export(typeof(A))]
    /// </summary>
    [Export]
    public class A : IA { }

    public class UseA
    {
        /// <summary>
        /// 等价于 [Import(typeof(A))]
        /// </summary>
        [Import]
        public A a { get; set; }

        /// <summary>
        /// 等价于 [Import(typeof(IA))]
        /// </summary>
        [Import]
        public IA ia { get; set; }
    }
  1. 含参数导入导出,要求类型和协定名完全匹配,未指定类型时,同上,使用当前声明的类或接口。

如下示例中,最终ib有效 ,而b是无效的。

    public interface IB { }

    [Export(typeof(IB))]
    public class B : IB { }

    public class UseB
    {
        [Import]
        public B b { get; set; }

        [Import]
        public IB ib { get; set; }
    }
  1. 延迟导入及导入多个;其中匹配类型时,均使用繁星内的类型。

在如下示例中,三个导入均有效。其中ImportMany主要用于多个具有相同协定名和类型的导出,如你有两个类使用了相同的类型和协定,用Import是会报错的,此时可以用ImportMany来处理。

    public interface IC { }

    [Export(typeof(IC))]
    public class C : IC { }

    public class UseC
    {
        [Import]
        public Lazy<IC> ic { get; set; }

        [ImportMany]
        public IEnumerable<IC> iclist { get; set; }

        [ImportMany]
        public IEnumerable<Lazy<IC>> icllist { get; set; }
    }

元数据

元数据可以简单理解为:针对具有相同协定和类型的导出,添加元数据来区分它们。

继承

在MEF中使用InheritedExport来设置继承导出,在继承结构中,导出的匹配类型为父类/接口的类型,示例如下:

在如下代码中,最后id是有效的,d是无效的,即类型D的导出继承ID,使用的类型为ID。

    [InheritedExport]
    public interface ID { }

    public class D : ID { }

    public class UseD
    {
        [Import]
        public D d { get; set; }

        [Import]
        public ID id { get; set; }
    }

结语

本文主要列出了最常用的导入导出参考,详细信息及更多扩展内容还是建议看微软官方文档:特性化编程模型概述 (MEF)


奇葩史

MEF基础指南——MEF首次接触

代码示例托管地址:MEF_First_Touch

简介

简单理解MEF就是.NET中的一个IOC框架。主要是为了增加开发的应用的扩展性的。目的其实和其他IOC框架一样,就是解耦。

何为IOC

IOC,即控制反转。

个人理解:
它其实是在接口的基础上进一步解耦,像我们一开始写接口,就是为了可以使用多种实现嘛,但是呢,你在使用过程中,在一个地方还是只能用一个(多个地方就要一个一个new,顶多用个工厂封装下,但你还得在用的地方告诉工厂使用哪个实现);
而此时IOC就可以有用了,它只需要你在使用的地方进行接口声明即可(顶多再加一些特殊的标识——看你用哪个IOC框架了),至于实例化哪个实现IOC框架来帮你做。这里不是你告诉IOC用哪个实现,而是告诉IOC我要什么样的处理,然后IOC来找对应匹配的实现。其实在这里面工厂和IOC很相似,甚至说不清,简单理解就是,工厂的实例化的控制权其实还是在具体使用工厂的地方,而IOC中实例化的控制权在IOC容器中。

下面举个例子描述下:

  • 工厂 —— 我到水果摊买水果,我告诉老板买啥水果,老板给我找对应的水果。 模式是:A——(B——C,D,E),B进行统筹管理
  • IOC —— 我到淘宝买水果,我告诉淘宝要啥水果,淘宝找出与我要的相匹配的水果。模式是:A——B——(C,D,E),B就进行接口匹配,找对应关系

如何使用

既然MEF是一个IOC框架,使用自然会需要以下三点:

  • 接口定义,相关实现
  • 接口声明 —— 使用
  • 通知IOC容器要处理啥

接口定义及相关实现定义

在MEF中实现的定义用导出来处理,本示例中,我们首先定义一个接口,然后添加一个实现,内容如下:

interface IStudy
{
    void Study();
}

[Export(typeof(IStudy))]
class MEFStudy : IStudy
{
    public void Study()
    {
        Console.WriteLine("Study MEF");
    }
}

使用实现

在MEF中要使用对应的实现,我们使用导入功能,代码如下:

[Import]
IStudy Study { get; set; }

调用内部方法则是:

Study.Study();

告诉IOC容器要处理的内容

在MEF中,这个处理里涉及的内容有容器和目录,具体使用如下:

//利用目录添加到容器
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

总结

至此,最简单的MEF使用就学会了。关于更多的导入导出等内容,后面将具体讨论。


奇葩史

关于使用到Xamarin.Android.Support相关dll无法生成问题解决

返回索引目录
参考内容: 个人yy,仅供参考

问题描述

由于在使用Xamarin.Android.Support相关的dll时,在生成项目期间需要到Google相应网站下载内容,故在国内常常会遇上生成不成功问题,其原因在于,无法下载相应的包。

解决方法:

  • 方案一:最简单也是最难的 —— 挂代理,对于会弄代理的,这个是最简单的,但对于搞不定代理、番羽(防叉叉)墙,这个就很麻烦了。

  • 方案二:离线处理 —— 关于离线处理,就得依赖网上友情人士提供压缩包了。

方案二离线处理之具体步骤

  • Xamarin.Android.Support相关的下载目录为C:\Users\你的用户名\AppData\Local\Xamarin,故离线处理只需将离线包下载放入zips目录下即可。
    • 如果你引用了Xamarin.Android.Support.v424.2.1版本,可以下载我下面给出的内容:【注意版本号,如果你使用的其他版本,则需要下载其他版本的】
  • 将上述下载到的压缩包直接放入C:\Users\你的用户名\AppData\Local\Xamarin\zips目录下。
    • 请注意:请勿修改压缩包名称 —— 依据个人每次生成名称一样得出的结论。
    • 如果你离线生成时,在C:\Users\你的用户名\AppData\Local\Xamarin\zips目录下生成的压缩包名称与我的不同,你可以用我给的替换下试试。—— 另望请告知。

另此离线处理非长久之法,毕竟现在Xamarin更新还是比较频繁的,此法更适合企业内网环境,所以建议能搞就搞个代理(更新及时)。

最后提供一个C盘瘦身内容

由于在Visual Studio生成Xamarin.Android项目时(在使用到Xamarin.Android.Support相关引用的情况下),会在C:\Users\你的用户名\AppData\Local\Xamarin目录下生成大量以Xamarin.Android.Support开头的文件夹;而此类文件夹是很大的,你可以将这一类文件夹删除 —— 但请注意不要删除zips内的文件,不然又得重新下了。

此法有一缺陷:删除后再次生成时会比较慢,所以建议在C盘比较紧张的情况下,去删除文件;或者是你更新版本了,可以将内部旧版文件删掉。


译:奇葩史

关于使用HttpClient请求返回中文乱码问题

本文内容为.NET平台中,使用HttpClient对某些中文网页进行请求时,遇上乱码问题解决方案整理。
个人遇到的网页即使是使用Postman也是乱码。

问题缘由

说到底就是charset的问题。在国内许多网站使用gb2312编码,导致直接使用Http请求默认转化乱码。一般utf-8的网站编码,不会遇上这个问题。

个人最终解决方案

先上代码:

此处代码中未使用异步功能,其中涉及的Async方法,在正式开发中,都可以利用await/async进行异步处理

HttpClient client = new HttpClient();
var responsestream = client.GetStreamAsync("http://www.shisujie.com").Result;
System.IO.StreamReader reader = new System.IO.StreamReader(responsestream, Encoding.GetEncoding("gb2312"));
string result = reader.ReadToEnd();

通过使用流的方式直接修改编码解析内容。

补充

上述方法我在第一天晚上认为可以,那天晚上确实可以了,然而第二天,又乱码了,一直不知道原因,后来在网上看到了关于gzip的,也就是说需要利用gzip解压。

最终代码如下:

var responsestream = client.GetStreamAsync("http://www.shisujie.com").Result;
GZipStream gz = new GZipStream(responsestream, CompressionMode.Decompress);
System.IO.StreamReader reader = new System.IO.StreamReader(gz, Encoding.GetEncoding("GB2312"));
string r = reader.ReadToEnd();

即使用GZipStream类型的数据流。

网络中提到的一些方案

方案一:修改响应头的charset值

var rep = client.GetAsync("http://www.shisujie.com").Result;
rep.Content.Headers.ContentType.CharSet = "gb2312"; 

此法还是较为靠谱的,但是针对我遇到的无效

方案二:将网页下载为本地文件

System.Net.WebClient client1 = new System.Net.WebClient();
client1.DownloadFile("http://www.shisujie.com/***", "D:\\test.html");

此法是个人网上资料一直解决不了问题后做的尝试,但一般网页正确下载应该是Windows(换行)格式+UTF-8编码;
而本人尝试的下载的文件是Unix(换行)格式+ANSI编码 —— 关键是http请求的编码应该是GB2312,所以最后很扯的没有成功。

方案三:使用字节流转化

var result = client.GetByteArrayAsync("http://www.shisujie.com").Result;
var r = Encoding.GetEncoding("GBK").GetString(result);

个人处理经历

仅供参考,以便于了解些问题解决思路

  • 首先确定是否是请求头问题,为请求头添加较为完整的信息
    • 包括Accept,AcceptLanguage等等,还有就是UserAgent,有些网站会对UserAgent判断。
  • 其次判断charset,也就是上面的方案一。
  • 后面还不行,还有判断是不是html编码,使用System.Net.WebUtility.HtmlDecode()转转格式看下。
  • 最后,就是抓包分析了 —— 不过好像在此次作用不大,我本以为是我发的http包有问题,就对比了下,尽管发的包不完全一样,但收到的结果完全一样啊 —— 即http请求正确,那就可以确定完全就是本地处理问题,就可以将重点放在本地数据流处理了。

奇葩史

百度网盘

百度网盘logo

百度网盘

隶属于百度公司,国内现在网盘挂的差不多了,也就百度依旧坚挺,具体到啥时候就不清楚了。

槽点

  • 同步盘相继停止更新:windows版2015-2、mac版 2015-7
  • 据说有限制用户下载-限速
  • 新版移动端加入了新闻功能,显得特臃肿
  • 小视频(及其他特殊内容)不能存,即使是私人不共享,传了就会被替换掉
  • 个人不反对收费,但信誉问题。。。。
  • 开发相关:相比国外大牌的云存储厂商,真的缺少完整api;相对太封闭。
    • 据说现在的psc各种限制

推荐

  • 相对来说,针对国内用户还是表示推荐使用的

基本介绍

相关链接

基本信息

  • 初始容量:已经不记得了,反正现在我总共有2159G
    • 免费扩展容量:2T
    • 收费扩展容量:5T
  • 地域:中国
    • 支持语言:简体中文
  • 外链分享:支持
  • 文件历史版本:支持
  • 成立/推出时间:2012-03-23

开发者相关

大事件

  • 2016-10 改名大法:正式改名为百度网盘,原名百度云

带你看看网盘的世界

本文内容后续会调整,初期为整理自己以前收藏的网盘内容,进行初步整理。有一些完全没打开的网站直接就删掉了。
由于国内个人云存储市场在晃荡,所以自己把以前收藏的网站准备拿出来整理下,好及时调整。

集成客户端——本地管理

  • AsLocal网盘本地管理专家 http://www.aslocal.com/ —— 本人需挂代理访问官网,可能是移动的墙

网盘资源搜索

网盘

国内

国外

已经挂掉的


掘:奇葩史

如何在Visual Studio中利用命令行集成Dotfuscator混淆处理

本文主要内容为使用命令行方式操作Dotfuscator,并将其集成到Visual Studio中,以便于直接生成发布。
另:本文使用的Dotfuscator版本为:集成在Visual Studio 2015 社区版中的Dotfuscator CE版本。

创建友好的Dotfuscator项目文件

Dotfuscator项目文件本质是一个xml,下文主要描述使用Dotfuscator可视化工具创建项目文件。

  1. 首先在Visual Studio中打开Dotfuscator:点击菜单栏中的工具 > PreEmptive Protection - Dotfuscator打开Dotfuscator。

  2. 此处默认新建了Dotfuscator项目,建议先进行保存,将文件保存至你要混淆项目的解决方案文件夹中,如,个人保存的位置为:E:\Projects\OpenSourceProject\ReferenceDoc\Dotfuscator\Samples\DotfuscatorSample\DotfuscatorSample.xml

保存到解决方案文件夹并非必须,此处如此处理可以为了后面进一步处理更加方便。

  1. 添加待混淆文件,如图所示:

添加待混淆文件

  1. 修改文件路径,将文件路径修改为如下图所示:点击属性,查看项目属性 - configdir(就是之前的保存位置),然后切换回输入,点击输入中第三个按钮编辑输入(那支笔),将路径中与configdir匹配的部分替换为**${configdir}**(注意是大括号)。

处理此步骤亦不是必须的,这样处理的原因是为了让我们的配置与本地无关(相对路径),方便其他人合作使用。

查看configdir

修改路径

  1. 至此,基本配置就可以了,点击生成项目就可以进行混淆了。至于其他更多配置见官方文档。

本地可以直接在Dotfuscator工具中点击菜单栏中的帮助 > 帮助目录(此为中文文档,基础的配置基本都有)。
帮助文件本地目录参考(中文帮助):C:\Program Files (x86)\Microsoft Visual Studio 14.0\PreEmptive Solutions\Dotfuscator and Analytics Community Edition\zh-Hans

配置Visual Studio命令调用Dotfuscator

  1. 主要操作就是编辑生成后事件:右击项目属性,切换到生成事件页面,编辑后期生成事件命令行,添加如下代码:

此处为了保证只有在Release的模式下使用混淆,故添加了Release判断。

    if $(ConfigurationName)==Release "C:\Program Files (x86)\Microsoft Visual Studio 14.0\PreEmptive Solutions\Dotfuscator and Analytics Community Edition\dotfuscatorcli.exe" /q "$(SolutionDir)DotfuscatorSample.xml"

代码解释:dotfuscator命令行工具+参数+项目混淆配置文件;其中配置文件之前保存到解决方案文件夹下,故此出可以直接用解决方案文件目录来索引。

代码中唯一不足就是命令行工具使用了绝对路径,vs中的宏参数没有可以直接使用的,若读者有啥好方法将此变为相对路径,望通知。 —— 但关于系统中添加环境变量的法子就不要了,个人不喜。

  1. 如果你在此处下一步需要进一步的打包处理,而你又需要Debug模式下一样可以打包测试。如,本人使用WiX打包,需要配置文件路径,方便一点就是要配置为生成路径,但是release模式下,需要将混淆的打包进去,而非直接生成的文件。此时,你不能改打包配置(改路径的话,debug会用不了),所以,你需要在将混淆过的文件拷贝到原来的release生成目录。所以我最后完整的生成事件就是如下代码了:

注意:经测试,如果在Dotfuscator中将生成路径设为文件来源路径,可以生成还会自动覆盖,但软件会用不了,具体原因不明。

    if $(ConfigurationName)==Release "C:\Program Files (x86)\Microsoft Visual Studio 14.0\PreEmptive Solutions\Dotfuscator and Analytics Community Edition\dotfuscatorcli.exe" /q "$(SolutionDir)DotfuscatorSample.xml"
    if $(ConfigurationName)==Release xcopy /e /y "$(SolutionDir)Dotfuscated\*.*" "$(TargetDir)" 

代码中的copy目录可以见Dotfuscator配置的生成目录:

查看Dotfuscator生成目录


奇葩史

关于Xamarin.Android中启用ProGuard后导致生成时java.exe错误问题解决

解决参考链接:

问题描述

选择启用Proguard后,进行项目生成操作,提示错误:“java.exe”已退出,代码为 1。

Proguard启用步骤:Xamarin.Android项目属性——Android Options页面——Packaging标签——勾选Enable Proguard

解决方法

  1. 下载最新版ProGuard的zip包(版本为5.3),下载地址为:https://sourceforge.net/projects/proguard/files/
  2. 由于ProGuard是没有安装程序的,故后面需要将zip解压到对应目录。
  3. 启动Android SDK Manager,查看菜单下方的SDK Path——查找sdk的位置。例如,我的位置是D:\Android\sdk(个人强迫症,调整过的),一般情况下,默认位置为C:\Users\你的用户名\AppData\Local\Android\android-sdk。而Proguard文件夹则位于此文件夹的tools文件夹中,如我的位置就是:D:\Android\sdk\tools\proguard
  4. 关闭所有可能访问SDK的开发环境(防止占用),然后将 proguard 文件夹命名为 proguard_old (用于备份,防止搞坏了可以恢复,另其中某些文件在下面还要用)。
  5. 将新版的proguard文件夹拷贝到tools文件夹中 —— 注意文件夹名称与上面原来的名称一样,这是为 proguard
  6. 最后,将配置文件从之前的 proguard_old 文件夹中拷贝到新的 proguard 文件夹中。一般是以下三个文件:proguard-android.txt, proguard-android-optimize.txtproguard-project.txt
  7. 最后的最后就是项目在启用ProGuard后重新生成了。

其他

关于其他ProGuard内容可以查看以下内容进一步学习:Xamarin.Android部署——应用程序发布准备


理:奇葩史